private ushort GetProperPrefetchSize(IPrioritySubscriptionOption subscriptionOption, uint priority) { var prefetchSize = subscriptionOption.QueuePrefetchSizeSelector != null ? subscriptionOption.QueuePrefetchSizeSelector(priority) : subscriptionOption.QueuePrefetchSize; if (prefetchSize <= 0) { prefetchSize = Global.PreFetchSize; } if (prefetchSize > ushort.MaxValue) { _watcher.WarnFormat("The prefetch size is too high {0}, the queue will prefetch the maximum {1} msgs", prefetchSize, ushort.MaxValue); } return((ushort)Math.Min(ushort.MaxValue, prefetchSize)); }
private string GetPriorityQueueName <T>(IPrioritySubscriptionOption subscriptionOption, uint priority) { return((subscriptionOption.RouteFinder ?? _routeFinder).FindQueueName <T>(subscriptionOption.SubscriptionName) + (subscriptionOption.QueueSuffixNameConvention ?? PriorityQueuesRabbitSetup.GlobalPriorityQueueSuffix).Get(typeof(T), priority)); }
private CompositeSubscription CreateSubscription <T>(IPrioritySubscriptionOption subscriptionOption, Func <IModel, string, IBasicConsumer> createConsumer) { var comparer = TryGetComparer(subscriptionOption.ComparerType); var compositeSubscription = new CompositeSubscription(); uint maxSize = 0; for (uint level = 0; level <= subscriptionOption.MaxPriorityLevel; level++) { maxSize += GetProperPrefetchSize(subscriptionOption, level); } var priorityQueue = new InMemoryPriorityQueue <GenericPriorityMessage <BasicDeliverEventArgs> >(maxSize, comparer); var sharedSemaphore = string.Format("{0}{1}", subscriptionOption.SubscriptionName, Guid.NewGuid()); for (uint level = 0; level <= subscriptionOption.MaxPriorityLevel; level++) { var subscription = new Subscription { SubscriptionName = subscriptionOption.SubscriptionName }; uint priority = level; var id = Guid.NewGuid(); Action subscriptionAction = () => { subscription.QueueName = GetPriorityQueueName <T>(subscriptionOption, priority); if (string.IsNullOrEmpty(subscription.ConsumerTag)) { // Keep the key here because it's used for the key indexes of internal cache subscription.ConsumerTag = string.Format("{0}-{1}", subscriptionOption.SubscriptionName, Guid.NewGuid()); } var channel = _connection.CreateChannel(); channel.ModelShutdown += (c, reason) => { RaiseConsumerDisconnectedEvent(subscription); TryReconnect(c, id, reason); }; var prefetchSize = GetProperPrefetchSize(subscriptionOption, priority); channel.BasicQos(0, prefetchSize, false); _createdChannels.Add(channel); var consumer = createConsumer(channel, subscription.ConsumerTag); var priorityConsumer = consumer as PriorityBurrowConsumer; if (priorityConsumer == null) { throw new NotSupportedException(string.Format("Expected PriorityBurrowConsumer but was {0}", consumer == null ? "NULL" : consumer.GetType().Name)); } priorityConsumer.Init(priorityQueue, compositeSubscription, priority, sharedSemaphore); priorityConsumer.ConsumerTag = subscription.ConsumerTag; subscription.SetChannel(channel); //NOTE: The message will still be on the Unacknowledged list until it's processed and the method // DoAck is call. channel.BasicConsume(subscription.QueueName, false /* noAck, must be false */, subscription.ConsumerTag, priorityConsumer); _watcher.InfoFormat("Subscribed to: {0} with subscriptionName: {1}", subscription.QueueName, subscription.SubscriptionName); priorityConsumer.Ready(); }; _subscribeActions[id] = subscriptionAction; TrySubscribe(subscriptionAction); compositeSubscription.AddSubscription(subscription); } return(compositeSubscription); }