Example #1
0
        public Task PublishAsync <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            return(PublishAsync(message, conventions.TopicNamingConvention(typeof(T))));
        }
Example #2
0
        public ConnectionFactoryWrapper(ConnectionConfiguration connectionConfiguration, IClusterHostSelectionStrategy <ConnectionFactoryInfo> clusterHostSelectionStrategy)
        {
            this.clusterHostSelectionStrategy = clusterHostSelectionStrategy;

            Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
            Preconditions.CheckAny(connectionConfiguration.Hosts, "connectionConfiguration", "At least one host must be defined in connectionConfiguration");

            Configuration = connectionConfiguration;

            foreach (var hostConfiguration in Configuration.Hosts)
            {
                var connectionFactory = new ConnectionFactory
                {
                    UseBackgroundThreadsForIO = connectionConfiguration.UseBackgroundThreads,
                    AutomaticRecoveryEnabled  = false,
                    TopologyRecoveryEnabled   = false
                };

                if (connectionConfiguration.AMQPConnectionString != null)
                {
                    connectionFactory.Uri = connectionConfiguration.AMQPConnectionString;
                }

                connectionFactory.HostName = hostConfiguration.Host;

                if (connectionFactory.VirtualHost == "/")
                {
                    connectionFactory.VirtualHost = Configuration.VirtualHost;
                }

                if (connectionFactory.UserName == "guest")
                {
                    connectionFactory.UserName = Configuration.UserName;
                }

                if (connectionFactory.Password == "guest")
                {
                    connectionFactory.Password = Configuration.Password;
                }

                if (connectionFactory.Port == -1)
                {
                    connectionFactory.Port = hostConfiguration.Port;
                }

                if (hostConfiguration.Ssl.Enabled)
                {
                    connectionFactory.Ssl = hostConfiguration.Ssl;
                }

                //Prefer SSL configurations per each host but fall back to ConnectionConfiguration's SSL configuration for backwards compatibility
                else if (Configuration.Ssl.Enabled)
                {
                    connectionFactory.Ssl = Configuration.Ssl;
                }

                connectionFactory.RequestedHeartbeat = TimeSpan.FromSeconds(Configuration.RequestedHeartbeat);
                connectionFactory.ClientProperties   = Configuration.ClientProperties;
                connectionFactory.AuthMechanisms     = Configuration.AuthMechanisms;
                clusterHostSelectionStrategy.Add(new ConnectionFactoryInfo(connectionFactory, hostConfiguration));
            }
        }
Example #3
0
 public virtual IAdvancedPublishChannel OpenPublishChannel(Action <IChannelConfiguration> configure)
 {
     Preconditions.CheckNotNull(configure, "configure");
     return(new RabbitAdvancedPublishChannel(this, configure));
 }
Example #4
0
        public void Publish <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            PublishAsync(message).Wait();
        }
Example #5
0
        /// <summary>
        /// Creates a new instance of <see cref="RabbitBus"/>.
        /// </summary>
        /// <param name="connectionString">
        /// The EasyNetQ connection string. Example:
        /// host=192.168.1.1;port=5672;virtualHost=MyVirtualHost;username=MyUsername;password=MyPassword;requestedHeartbeat=10
        ///
        /// The following default values will be used if not specified:
        /// host=localhost;port=5672;virtualHost=/;username=guest;password=guest;requestedHeartbeat=10
        /// </param>
        /// <param name="registerServices">
        /// Override default services. For example, to override the default <see cref="ISerializer"/>:
        /// RabbitHutch.CreateBus("host=localhost", x => x.Register{ISerializer}(mySerializer));
        /// </param>
        /// <returns>
        /// A new <see cref="RabbitBus"/> instance.
        /// </returns>
        public static IBus CreateBus(string connectionString, Action <IServiceRegister> registerServices)
        {
            Preconditions.CheckNotNull(connectionString, "connectionString");

            return(CreateBus(x => x.Resolve <IConnectionStringParser>().Parse(connectionString), registerServices));
        }
Example #6
0
        /// <summary>
        /// Creates a new instance of RabbitBus.
        /// </summary>
        /// <param name="connectionString">
        /// The EasyNetQ connection string. Example:
        /// host=192.168.1.1;port=5672;virtualHost=MyVirtualHost;username=MyUsername;password=MyPassword;requestedHeartbeat=10
        ///
        /// The following default values will be used if not specified:
        /// host=localhost;port=5672;virtualHost=/;username=guest;password=guest;requestedHeartbeat=10
        /// </param>
        /// <returns>
        /// A new RabbitBus instance.
        /// </returns>
        public static IBus CreateBus(string connectionString)
        {
            Preconditions.CheckNotNull(connectionString, "connectionString");

            return(CreateBus(connectionString, x => {}));
        }
Example #7
0
        public virtual async Task PublishAsync(
            IExchange exchange,
            string routingKey,
            bool mandatory,
            MessageProperties messageProperties,
            byte[] body)
        {
            Preconditions.CheckNotNull(exchange, "exchange");
            Preconditions.CheckShortString(routingKey, "routingKey");
            Preconditions.CheckNotNull(messageProperties, "messageProperties");
            Preconditions.CheckNotNull(body, "body");

            // Fix me: It's very hard now to move publish logic to separate abstraction, just leave it here.
            var rawMessage = produceConsumeInterceptor.OnProduce(new RawMessage(messageProperties, body));

            if (connectionConfiguration.PublisherConfirms)
            {
                var timeBudget = new TimeBudget(TimeSpan.FromSeconds(connectionConfiguration.Timeout)).Start();
                while (!timeBudget.IsExpired())
                {
                    var confirmsWaiter = await clientCommandDispatcher.InvokeAsync(model =>
                    {
                        var properties = model.CreateBasicProperties();
                        rawMessage.Properties.CopyTo(properties);
                        var waiter = confirmationListener.GetWaiter(model);

                        try
                        {
                            model.BasicPublish(exchange.Name, routingKey, mandatory, properties, rawMessage.Body);
                        }
                        catch (Exception)
                        {
                            waiter.Cancel();
                            throw;
                        }

                        return(waiter);
                    }).ConfigureAwait(false);

                    try
                    {
                        await confirmsWaiter.WaitAsync(timeBudget.GetRemainingTime()).ConfigureAwait(false);

                        break;
                    }
                    catch (PublishInterruptedException)
                    {
                    }
                }
            }
            else
            {
                await clientCommandDispatcher.InvokeAsync(model =>
                {
                    var properties = model.CreateBasicProperties();
                    rawMessage.Properties.CopyTo(properties);
                    model.BasicPublish(exchange.Name, routingKey, mandatory, properties, rawMessage.Body);
                }).ConfigureAwait(false);
            }
            eventBus.Publish(new PublishedMessageEvent(exchange.Name, routingKey, rawMessage.Properties, rawMessage.Body));
            logger.DebugWrite("Published to exchange: '{0}', routing key: '{1}', correlationId: '{2}'", exchange.Name, routingKey, messageProperties.CorrelationId);
        }
Example #8
0
        public void CopyTo(IBasicProperties basicProperties)
        {
            Preconditions.CheckNotNull(basicProperties, "basicProperties");

            if (contentTypePresent)
            {
                basicProperties.ContentType = ContentType;
            }
            if (contentEncodingPresent)
            {
                basicProperties.ContentEncoding = ContentEncoding;
            }
            if (deliveryModePresent)
            {
                basicProperties.DeliveryMode = DeliveryMode;
            }
            if (priorityPresent)
            {
                basicProperties.Priority = Priority;
            }
            if (correlationIdPresent)
            {
                basicProperties.CorrelationId = CorrelationId;
            }
            if (replyToPresent)
            {
                basicProperties.ReplyTo = ReplyTo;
            }
            if (expirationPresent)
            {
                basicProperties.Expiration = Expiration;
            }
            if (messageIdPresent)
            {
                basicProperties.MessageId = MessageId;
            }
            if (timestampPresent)
            {
                basicProperties.Timestamp = new AmqpTimestamp(Timestamp);
            }
            if (typePresent)
            {
                basicProperties.Type = Type;
            }
            if (userIdPresent)
            {
                basicProperties.UserId = UserId;
            }
            if (appIdPresent)
            {
                basicProperties.AppId = AppId;
            }
            if (clusterIdPresent)
            {
                basicProperties.ClusterId = ClusterId;
            }

            if (headersPresent)
            {
                basicProperties.Headers = new Dictionary <string, object>(Headers);
            }
        }
Example #9
0
        /// <summary>
        /// Publishes a message with a topic
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="topic">The topic string</param>
        /// <param name="cancellationToken">The cancellation token</param>
        public static void Publish <T>(this IPubSub pubSub, T message, string topic, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            pubSub.Publish(message, c => c.WithTopic(topic), cancellationToken);
        }
Example #10
0
        public RabbitAdvancedBus(
            IConnectionFactory connectionFactory,
            IConsumerFactory consumerFactory,
            IEasyNetQLogger logger,
            IClientCommandDispatcherFactory clientCommandDispatcherFactory,
            IPublishConfirmationListener confirmationListener,
            IEventBus eventBus,
            IHandlerCollectionFactory handlerCollectionFactory,
            IContainer container,
            ConnectionConfiguration connectionConfiguration,
            IProduceConsumeInterceptor produceConsumeInterceptor,
            IMessageSerializationStrategy messageSerializationStrategy,
            IConventions conventions,
            AdvancedBusEventHandlers advancedBusEventHandlers,
            IPersistentConnectionFactory persistentConnectionFactory)
        {
            Preconditions.CheckNotNull(connectionFactory, "connectionFactory");
            Preconditions.CheckNotNull(consumerFactory, "consumerFactory");
            Preconditions.CheckNotNull(logger, "logger");
            Preconditions.CheckNotNull(eventBus, "eventBus");
            Preconditions.CheckNotNull(handlerCollectionFactory, "handlerCollectionFactory");
            Preconditions.CheckNotNull(container, "container");
            Preconditions.CheckNotNull(messageSerializationStrategy, "messageSerializationStrategy");
            Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
            Preconditions.CheckNotNull(produceConsumeInterceptor, "produceConsumeInterceptor");
            Preconditions.CheckNotNull(conventions, "conventions");
            Preconditions.CheckNotNull(advancedBusEventHandlers, "advancedBusEventHandlers");
            Preconditions.CheckNotNull(persistentConnectionFactory, "persistentConnectionFactory");

            this.consumerFactory              = consumerFactory;
            this.logger                       = logger;
            this.confirmationListener         = confirmationListener;
            this.eventBus                     = eventBus;
            this.handlerCollectionFactory     = handlerCollectionFactory;
            this.Container                    = container;
            this.connectionConfiguration      = connectionConfiguration;
            this.produceConsumeInterceptor    = produceConsumeInterceptor;
            this.messageSerializationStrategy = messageSerializationStrategy;
            this.Conventions                  = conventions;

            this.eventBus.Subscribe <ConnectionCreatedEvent>(e => OnConnected());
            if (advancedBusEventHandlers.Connected != null)
            {
                Connected += advancedBusEventHandlers.Connected;
            }
            this.eventBus.Subscribe <ConnectionDisconnectedEvent>(e => OnDisconnected());
            if (advancedBusEventHandlers.Disconnected != null)
            {
                Disconnected += advancedBusEventHandlers.Disconnected;
            }
            this.eventBus.Subscribe <ConnectionBlockedEvent>(OnBlocked);
            if (advancedBusEventHandlers.Blocked != null)
            {
                Blocked += advancedBusEventHandlers.Blocked;
            }
            this.eventBus.Subscribe <ConnectionUnblockedEvent>(e => OnUnblocked());
            if (advancedBusEventHandlers.Unblocked != null)
            {
                Unblocked += advancedBusEventHandlers.Unblocked;
            }
            this.eventBus.Subscribe <ReturnedMessageEvent>(OnMessageReturned);
            if (advancedBusEventHandlers.MessageReturned != null)
            {
                MessageReturned += advancedBusEventHandlers.MessageReturned;
            }

            connection = persistentConnectionFactory.CreateConnection();
            clientCommandDispatcher = clientCommandDispatcherFactory.GetClientCommandDispatcher(connection);
            connection.Initialize();
        }
Example #11
0
        public virtual void Consume(IQueue queue, Func <Byte[], MessageProperties, MessageReceivedInfo, Task> onMessage)
        {
            Preconditions.CheckNotNull(queue, "queue");
            Preconditions.CheckNotNull(onMessage, "onMessage");

            if (disposed)
            {
                throw new EasyNetQException("This bus has been disposed");
            }

            var newConsumerTag     = conventions.ConsumerTagConvention();
            var subscriptionAction = new SubscriptionAction(newConsumerTag, logger, queue.IsSingleUse, queue.IsExclusive);

            subscriptionAction.Action = (isNewConnection) =>
            {
                // recreate channel if current channel is no longer open or connection was dropped and reconnected (to survive server restart)
                if (subscriptionAction.Channel == null || subscriptionAction.Channel.IsOpen == false || isNewConnection)
                {
                    subscriptionAction.Channel = CreateChannel(queue);
                }

                var channel = subscriptionAction.Channel;

                channel.BasicQos(0, connectionConfiguration.PrefetchCount, false);

                var consumer = consumerFactory.CreateConsumer(subscriptionAction, channel, queue.IsSingleUse,
                                                              (consumerTag, deliveryTag, redelivered, exchange, routingKey, properties, body) =>
                {
                    var messageRecievedInfo = new MessageReceivedInfo
                    {
                        ConsumerTag = consumerTag,
                        DeliverTag  = deliveryTag,
                        Redelivered = redelivered,
                        Exchange    = exchange,
                        RoutingKey  = routingKey
                    };
                    var messsageProperties = new MessageProperties(properties);
                    return(onMessage(body, messsageProperties, messageRecievedInfo));
                });

                var cancelNotifications = consumer as IConsumerCancelNotifications;
                if (cancelNotifications != null)
                {
                    cancelNotifications.BasicCancel += OnBasicCancel;
                }

                channel.BasicConsume(
                    queue.Name,             // queue
                    NoAck,                  // noAck
                    consumer.ConsumerTag,   // consumerTag
                    consumer);              // consumer

                logger.DebugWrite("Declared Consumer. queue='{0}', consumer tag='{1}' prefetchcount={2}",
                                  queue.Name,
                                  consumer.ConsumerTag,
                                  connectionConfiguration.PrefetchCount);
            };



            AddSubscriptionAction(subscriptionAction);
        }
 public void Add(T item)
 {
     Preconditions.CheckNotNull(item, "item");
     items.Add(item);
     items.Shuffle();
 }
Example #13
0
        /// <summary>
        /// Creates a new instance of <see cref="RabbitBus"/>.
        /// </summary>
        /// <param name="connectionString">
        /// The EasyNetQ connection string. Example:
        /// host=192.168.1.1;port=5672;virtualHost=MyVirtualHost;username=MyUsername;password=MyPassword;requestedHeartbeat=10
        /// 
        /// The following default values will be used if not specified:
        /// host=localhost;port=5672;virtualHost=/;username=guest;password=guest;requestedHeartbeat=10
        /// </param>
        /// <returns>
        /// A new <see cref="RabbitBus"/> instance.
        /// </returns>
        public static IBus CreateBus(string connectionString)
        {
            Preconditions.CheckNotNull(connectionString, "connectionString");

            return CreateBus(connectionString, AdvancedBusEventHandlers.Default);
        }
 public TimeoutStrategy(ConnectionConfiguration connectionConfiguration)
 {
     Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
     this.connectionConfiguration = connectionConfiguration;
 }
Example #15
0
        public async Task <IQueue> QueueDeclareAsync(
            string name,
            bool passive                = false,
            bool durable                = true,
            bool exclusive              = false,
            bool autoDelete             = false,
            int?perQueueMessageTtl      = null,
            int?expires                 = null,
            int?maxPriority             = null,
            string deadLetterExchange   = null,
            string deadLetterRoutingKey = null,
            int?maxLength               = null,
            int?maxLengthBytes          = null)
        {
            Preconditions.CheckNotNull(name, "name");

            if (passive)
            {
                await clientCommandDispatcher.InvokeAsync(x => x.QueueDeclarePassive(name)).ConfigureAwait(false);

                return(new Queue(name, exclusive));
            }

            var arguments = new Dictionary <string, object>();

            if (perQueueMessageTtl.HasValue)
            {
                arguments.Add("x-message-ttl", perQueueMessageTtl.Value);
            }
            if (expires.HasValue)
            {
                arguments.Add("x-expires", expires);
            }
            if (maxPriority.HasValue)
            {
                arguments.Add("x-max-priority", maxPriority.Value);
            }
            // Allow empty dead-letter-exchange as it represents the default rabbitmq exchange
            // and thus is a valid value. To dead-letter a message directly to a queue, you
            // would set dead-letter-exchange to empty and dead-letter-routing-key to name of the
            // queue since every queue has a direct binding with default exchange.
            if (deadLetterExchange != null)
            {
                arguments.Add("x-dead-letter-exchange", deadLetterExchange);
            }
            if (!string.IsNullOrEmpty(deadLetterRoutingKey))
            {
                arguments.Add("x-dead-letter-routing-key", deadLetterRoutingKey);
            }
            if (maxLength.HasValue)
            {
                arguments.Add("x-max-length", maxLength.Value);
            }
            if (maxLengthBytes.HasValue)
            {
                arguments.Add("x-max-length-bytes", maxLengthBytes.Value);
            }

            await clientCommandDispatcher.InvokeAsync(x => x.QueueDeclare(name, durable, exclusive, autoDelete, arguments)).ConfigureAwait(false);

            logger.DebugWrite("Declared Queue: '{0}', durable:{1}, exclusive:{2}, autoDelete:{3}, args:{4}", name, durable, exclusive, autoDelete, string.Join(", ", arguments.Select(kvp =>
                                                                                                                                                                                      $"{kvp.Key}={kvp.Value}")));
            return(new Queue(name, exclusive));
        }
Example #16
0
        public void CopyFrom(IBasicProperties basicProperties)
        {
            Preconditions.CheckNotNull(basicProperties, "basicProperties");

            if (basicProperties.IsContentTypePresent())
            {
                ContentType = basicProperties.ContentType;
            }
            if (basicProperties.IsContentEncodingPresent())
            {
                ContentEncoding = basicProperties.ContentEncoding;
            }
            if (basicProperties.IsDeliveryModePresent())
            {
                DeliveryMode = basicProperties.DeliveryMode;
            }
            if (basicProperties.IsPriorityPresent())
            {
                Priority = basicProperties.Priority;
            }
            if (basicProperties.IsCorrelationIdPresent())
            {
                CorrelationId = basicProperties.CorrelationId;
            }
            if (basicProperties.IsReplyToPresent())
            {
                ReplyTo = basicProperties.ReplyTo;
            }
            if (basicProperties.IsExpirationPresent())
            {
                Expiration = basicProperties.Expiration;
            }
            if (basicProperties.IsMessageIdPresent())
            {
                MessageId = basicProperties.MessageId;
            }
            if (basicProperties.IsTimestampPresent())
            {
                Timestamp = basicProperties.Timestamp.UnixTime;
            }
            if (basicProperties.IsTypePresent())
            {
                Type = basicProperties.Type;
            }
            if (basicProperties.IsUserIdPresent())
            {
                UserId = basicProperties.UserId;
            }
            if (basicProperties.IsAppIdPresent())
            {
                AppId = basicProperties.AppId;
            }
            if (basicProperties.IsClusterIdPresent())
            {
                ClusterId = basicProperties.ClusterId;
            }

            if (basicProperties.IsHeadersPresent())
            {
                foreach (var header in basicProperties.Headers)
                {
                    Headers.Add(header.Key, header.Value);
                }
            }
        }
        /// <summary>
        /// Publishes a message.
        /// </summary>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="messageType">The message type</param>
        /// <param name="cancellationToken">The cancellation token</param>
        public static void Publish(this IPubSub pubSub, object message, Type messageType, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            pubSub.Publish(message, messageType, c => { }, cancellationToken);
        }
Example #18
0
        /// <summary>
        /// Creates a new instance of <see cref="RabbitBus"/>.
        /// </summary>
        /// <param name="connectionConfiguration">
        /// An <see cref="ConnectionConfiguration"/> instance.
        /// </param>
        /// <param name="registerServices">
        /// Override default services. For example, to override the default <see cref="ISerializer"/>:
        /// RabbitHutch.CreateBus("host=localhost", x => x.Register{ISerializer}(mySerializer));
        /// </param>
        /// <returns>
        /// A new <see cref="RabbitBus"/> instance.
        /// </returns>
        public static IBus CreateBus(ConnectionConfiguration connectionConfiguration, Action <IServiceRegister> registerServices)
        {
            Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");

            return(CreateBus(_ => connectionConfiguration, registerServices));
        }
        /// <summary>
        /// Publishes a message with a topic.
        /// When used with publisher confirms the task completes when the publish is confirmed.
        /// Task will throw an exception if the confirm is NACK'd or times out.
        /// </summary>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="messageType">The message type</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns></returns>
        public static Task PublishAsync(this IPubSub pubSub, object message, Type messageType, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            return(pubSub.PublishAsync(message, messageType, c => { }, cancellationToken));
        }
Example #20
0
        /// <summary>
        /// Set the container creation function. This allows you to replace EasyNetQ's default internal
        /// IoC container. Note that all components should be registered as singletons. EasyNetQ will
        /// also call Dispose on components that are no longer required.
        /// </summary>
        public static void SetContainerFactory(Func <IContainer> createContainer)
        {
            Preconditions.CheckNotNull(createContainer, "createContainer");

            createContainerInternal = createContainer;
        }
Example #21
0
        public virtual void Publish <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            Publish(message, conventions.TopicNamingConvention(typeof(T)));
        }
Example #22
0
 public static string Serialize(Type type)
 {
     Preconditions.CheckNotNull(type, "type");
     return(type.FullName.Replace('.', '_') + ":" + type.Assembly.GetName().Name.Replace('.', '_'));
 }
Example #23
0
        public virtual IQueue QueueDeclare(
            string name,
            bool passive                = false,
            bool durable                = true,
            bool exclusive              = false,
            bool autoDelete             = false,
            int?perQueueMessageTtl      = null,
            int?expires                 = null,
            int?maxPriority             = null,
            string deadLetterExchange   = null,
            string deadLetterRoutingKey = null,
            int?maxLength               = null,
            int?maxLengthBytes          = null)
        {
            Preconditions.CheckNotNull(name, "name");

            if (passive)
            {
                clientCommandDispatcher.Invoke(x => x.QueueDeclarePassive(name));
                return(new Queue(name, exclusive));
            }

            var arguments = new Dictionary <string, object>();

            if (perQueueMessageTtl.HasValue)
            {
                arguments.Add("x-message-ttl", perQueueMessageTtl.Value);
            }
            if (expires.HasValue)
            {
                arguments.Add("x-expires", expires);
            }
            if (maxPriority.HasValue)
            {
                arguments.Add("x-max-priority", maxPriority.Value);
            }
            // Allow empty dead-letter-exchange as it represents the default rabbitmq exchange
            // and thus is a valid value. To dead-letter a message directly to a queue, you
            // would set dead-letter-exchange to empty and dead-letter-routing-key to name of the
            // queue since every queue has a direct binding with default exchange.
            if (deadLetterExchange != null)
            {
                arguments.Add("x-dead-letter-exchange", deadLetterExchange);
            }
            if (!string.IsNullOrEmpty(deadLetterRoutingKey))
            {
                arguments.Add("x-dead-letter-routing-key", deadLetterRoutingKey);
            }
            if (maxLength.HasValue)
            {
                arguments.Add("x-max-length", maxLength.Value);
            }
            if (maxLengthBytes.HasValue)
            {
                arguments.Add("x-max-length-bytes", maxLengthBytes.Value);
            }

            var queueDeclareOk = clientCommandDispatcher.Invoke(x => x.QueueDeclare(name, durable, exclusive, autoDelete, arguments));

            if (logger.IsDebugEnabled())
            {
                logger.DebugFormat(
                    "Declared queue {queue}: durable={durable}, exclusive={exclusive}, autoDelete={autoDelete}, arguments={arguments}",
                    queueDeclareOk.QueueName,
                    durable,
                    exclusive,
                    autoDelete,
                    arguments.Stringify()
                    );
            }

            return(new Queue(queueDeclareOk.QueueName, exclusive));
        }