public Task <IExchange> DeclareExchangeAsync(IAdvancedBus advancedBus, string exchangeName, string exchangeType)
 {
     return(exchangeNames.AddOrUpdate(
                exchangeName,
                name => advancedBus.ExchangeDeclareAsync(name, exchangeType),
                (name, exchangeTask) => exchangeTask.IsFaulted ? advancedBus.ExchangeDeclareAsync(name, exchangeType) : exchangeTask));
 }
        private async Task FuturePublishInternalAsync <T>(TimeSpan messageDelay, T message, string cancellationKey = null) where T : class
        {
            Preconditions.CheckNotNull(message, "message");
            Preconditions.CheckLess(messageDelay, MaxMessageDelay, "messageDelay");
            Preconditions.CheckNull(cancellationKey, "cancellationKey");

            var exchangeName       = conventions.ExchangeNamingConvention(typeof(T));
            var futureExchangeName = exchangeName + "_delayed";
            var queueName          = conventions.QueueNamingConvention(typeof(T), null);
            var futureExchange     = await advancedBus.ExchangeDeclareAsync(futureExchangeName, ExchangeType.Direct, delayed : true).ConfigureAwait(false);

            var exchange = await advancedBus.ExchangeDeclareAsync(exchangeName, ExchangeType.Topic).ConfigureAwait(false);

            await advancedBus.BindAsync(futureExchange, exchange, "#").ConfigureAwait(false);

            var queue = await advancedBus.QueueDeclareAsync(queueName).ConfigureAwait(false);

            await advancedBus.BindAsync(exchange, queue, "#").ConfigureAwait(false);

            var easyNetQMessage = new Message <T>(message)
            {
                Properties =
                {
                    DeliveryMode = messageDeliveryModeStrategy.GetDeliveryMode(typeof(T)),
                    Headers      = new Dictionary <string,                                object>{
                        { "x-delay", (int)messageDelay.TotalMilliseconds }
                    }
                }
            };
            await advancedBus.PublishAsync(futureExchange, "#", false, false, easyNetQMessage).ConfigureAwait(false);
        }
 public Task<IExchange> DeclareExchangeAsync(IAdvancedBus advancedBus, string exchangeName, string exchangeType)
 {
     return exchangeNames.AddOrUpdate(
         exchangeName,
         name => advancedBus.ExchangeDeclareAsync(name, exchangeType),
         (name, exchangeTask) => exchangeTask.IsFaulted ? advancedBus.ExchangeDeclareAsync(name, exchangeType) : exchangeTask);
 }
예제 #4
0
 public EasyNetQPublisher(IAdvancedBus bus, string exchangename, IModelNamingConventionController modelNamingConventionController)
 {
     _bus      = bus;
     _exchange = new AsyncLazy <IExchange>(async() =>
                                           await _bus.ExchangeDeclareAsync(exchangename, ExchangeType.Topic));
     _modelNamingConventionController = modelNamingConventionController;
 }
예제 #5
0
        public async Task <IExchange> DeclareExchangeAsync(IAdvancedBus advancedBus, string exchangeName, string exchangeType)
        {
            IExchange exchange;

            if (exchanges.TryGetValue(exchangeName, out exchange))
            {
                return(exchange);
            }
            await semaphore.WaitAsync().ConfigureAwait(false);

            try
            {
                if (exchanges.TryGetValue(exchangeName, out exchange))
                {
                    return(exchange);
                }
                exchange = await advancedBus.ExchangeDeclareAsync(exchangeName, exchangeType).ConfigureAwait(false);

                exchanges[exchangeName] = exchange;
                return(exchange);
            }
            finally
            {
                semaphore.Release();
            }
        }
예제 #6
0
        private async Task FuturePublishInternalAsync <T>(TimeSpan messageDelay, T message, string cancellationKey) where T : class
        {
            Preconditions.CheckNotNull(message, "message");
            Preconditions.CheckLess(messageDelay, MaxMessageDelay, "messageDelay");
            Preconditions.CheckNull(cancellationKey, "cancellationKey");
            var delay              = Round(messageDelay);
            var delayString        = delay.ToString(@"dd\_hh\_mm\_ss");
            var exchangeName       = conventions.ExchangeNamingConvention(typeof(T));
            var futureExchangeName = exchangeName + "_" + delayString;
            var futureQueueName    = conventions.QueueNamingConvention(typeof(T), delayString);
            var futureExchange     = await advancedBus.ExchangeDeclareAsync(futureExchangeName, ExchangeType.Topic).ConfigureAwait(false);

            var futureQueue = await advancedBus.QueueDeclareAsync(futureQueueName, perQueueMessageTtl : (int)delay.TotalMilliseconds, deadLetterExchange : exchangeName).ConfigureAwait(false);

            await advancedBus.BindAsync(futureExchange, futureQueue, "#").ConfigureAwait(false);

            var easyNetQMessage = new Message <T>(message)
            {
                Properties =
                {
                    DeliveryMode = messageDeliveryModeStrategy.GetDeliveryMode(typeof(T))
                }
            };
            await advancedBus.PublishAsync(futureExchange, "#", false, false, easyNetQMessage).ConfigureAwait(false);
        }
예제 #7
0
        public async Task Publish <T>(string publishedLanguageEntity, T message, long sequence)
        {
            var exchange = await _messageBus.ExchangeDeclareAsync(NamingConventions.ExchangeNamingConvention(_boundedContextName, publishedLanguageEntity),
                                                                  ExchangeType.Topic);

            await Publish(exchange, "", message, sequence);
        }
예제 #8
0
        /// <summary>
        /// Creates an exchange on the message broker.  If the exchange is the default exchange
        /// with a defined queue, the queue is created on the RabbitMQ default exchange.
        /// </summary>
        /// <param name="bus">Reference to the advanced bus.</param>
        /// <param name="meta">The metadata describing the exchange.</param>
        /// <returns>Reference to the created exchange.</returns>
        public static async Task <IExchange> ExchangeDeclareAsync(this IAdvancedBus bus, ExchangeMeta meta)
        {
            if (bus == null)
            {
                throw new ArgumentNullException(nameof(bus));
            }
            if (meta == null)
            {
                throw new ArgumentNullException(nameof(meta));
            }

            // If the queue meta is specified on the exchange meta, this indicates that
            // a queue should be created on the default exchange.
            // https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-default
            if (meta.QueueMeta != null)
            {
                await bus.QueueDeclareAsync(meta.QueueMeta.ScopedQueueName,
                                            durable : meta.QueueMeta.IsDurable,
                                            autoDelete : meta.QueueMeta.IsAutoDelete,
                                            exclusive : meta.QueueMeta.IsExclusive,
                                            passive : meta.QueueMeta.IsPassive,
                                            maxPriority : meta.QueueMeta.MaxPriority,
                                            deadLetterExchange : meta.QueueMeta.DeadLetterExchange,
                                            deadLetterRoutingKey : meta.QueueMeta.DeadLetterRoutingKey,
                                            perQueueMessageTtl : meta.QueueMeta.PerQueueMessageTtl).ConfigureAwait(false);

                return(Exchange.GetDefault());
            }

            return(await bus.ExchangeDeclareAsync(meta.ExchangeName, meta.ExchangeType,
                                                  durable : meta.IsDurable,
                                                  autoDelete : meta.IsAutoDelete,
                                                  passive : meta.IsPassive,
                                                  alternateExchange : meta.AlternateExchangeName).ConfigureAwait(false));
        }
예제 #9
0
        public Task FuturePublishAsync <T>(TimeSpan messageDelay, T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");
            Preconditions.CheckLess(messageDelay, MaxMessageDelay, "messageDelay");
            var delay              = Round(messageDelay);
            var delayString        = delay.ToString(@"dd\_hh\_mm\_ss");
            var exchangeName       = conventions.ExchangeNamingConvention(typeof(T));
            var futureExchangeName = exchangeName + "_" + delayString;
            var futureQueueName    = conventions.QueueNamingConvention(typeof(T), delayString);

            return(advancedBus.ExchangeDeclareAsync(futureExchangeName, ExchangeType.Topic)
                   .Then(futureExchange => advancedBus.QueueDeclareAsync(futureQueueName, perQueueTtl: (int)delay.TotalMilliseconds, deadLetterExchange: exchangeName)
                         .Then(futureQueue => advancedBus.BindAsync(futureExchange, futureQueue, "#"))
                         .Then(() =>
            {
                var easyNetQMessage = new Message <T>(message)
                {
                    Properties =
                    {
                        DeliveryMode = (byte)(messageDeliveryModeStrategy.IsPersistent(typeof(T)) ? 2 : 1)
                    }
                };
                return advancedBus.PublishAsync(futureExchange, "#", false, false, easyNetQMessage);
            })));
        }
        public DefaultExchangeDeclareStrategy(IConventions conventions, IAdvancedBus advancedBus)
        {
            Preconditions.CheckNotNull(conventions, "conventions");
            Preconditions.CheckNotNull(advancedBus, "advancedBus");

            this.conventions  = conventions;
            declaredExchanges = new AsyncCache <ExchangeKey, IExchange>((k, c) => advancedBus.ExchangeDeclareAsync(k.Name, k.Type, cancellationToken: c));
        }
예제 #11
0
        /// <inheritdoc />
        public async Task FuturePublishAsync <T>(
            T message,
            TimeSpan delay,
            Action <IFuturePublishConfiguration> configure,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(message, "message");
            Preconditions.CheckNotNull(configure, "configure");

            using var cts = cancellationToken.WithTimeout(configuration.Timeout);

            var publishConfiguration = new FuturePublishConfiguration(conventions.TopicNamingConvention(typeof(T)));

            configure(publishConfiguration);

            var topic              = publishConfiguration.Topic;
            var exchangeName       = conventions.ExchangeNamingConvention(typeof(T));
            var futureExchangeName = exchangeName + "_delayed";
            var futureExchange     = await advancedBus.ExchangeDeclareAsync(
                futureExchangeName,
                c => c.AsDelayedExchange(ExchangeType.Topic),
                cts.Token
                ).ConfigureAwait(false);

            var exchange = await advancedBus.ExchangeDeclareAsync(
                exchangeName,
                c => c.WithType(ExchangeType.Topic),
                cts.Token
                ).ConfigureAwait(false);

            await advancedBus.BindAsync(futureExchange, exchange, topic, cts.Token).ConfigureAwait(false);

            var properties = new MessageProperties();

            if (publishConfiguration.Priority != null)
            {
                properties.Priority = publishConfiguration.Priority.Value;
            }
            properties.DeliveryMode = messageDeliveryModeStrategy.GetDeliveryMode(typeof(T));

            await advancedBus.PublishAsync(
                futureExchange, topic, false, new Message <T>(message, properties).WithDelay(delay), cts.Token
                ).ConfigureAwait(false);
        }
예제 #12
0
        /// <summary>
        /// Creates a queue and its associated exchange on the message broker.  If the associated
        /// exchange is the RabbitMQ default exchange, only the queue is created.  For a non-default
        /// exchange, the queue is bound to the exchange.  If the metadata has route-keys specified,
        /// the queue is bound the to exchange for each specified key.
        /// </summary>
        /// <param name="bus">Reference to the advanced bus.</param>
        /// <param name="meta">The metadata describing the queue.</param>
        /// <returns>Reference to the created queue.</returns>
        public static async Task <IQueue> QueueDeclare(this IAdvancedBus bus, QueueMeta meta)
        {
            if (bus == null)
            {
                throw new ArgumentNullException(nameof(bus));
            }
            if (meta == null)
            {
                throw new ArgumentNullException(nameof(meta));
            }

            IExchange    exchange     = Exchange.GetDefault(); //  Assume default exchange.
            ExchangeMeta exchangeMeta = meta.Exchange;

            if (!meta.Exchange.IsDefaultExchange)
            {
                exchange = await bus.ExchangeDeclareAsync(exchangeMeta.ExchangeName, exchangeMeta.ExchangeType,
                                                          durable : exchangeMeta.IsDurable,
                                                          autoDelete : exchangeMeta.IsAutoDelete,
                                                          passive : exchangeMeta.IsPassive,
                                                          alternateExchange : exchangeMeta.AlternateExchangeName);
            }

            IQueue queue = await bus.QueueDeclareAsync(meta.ScopedQueueName,
                                                       durable : meta.IsDurable,
                                                       autoDelete : meta.IsAutoDelete,
                                                       exclusive : meta.IsExclusive,
                                                       passive : meta.IsPassive,
                                                       maxPriority : meta.MaxPriority,
                                                       deadLetterExchange : meta.DeadLetterExchange,
                                                       deadLetterRoutingKey : meta.DeadLetterRoutingKey,
                                                       perQueueMessageTtl : meta.PerQueueMessageTtl);


            // Queues defined on the default exchange so don't bind.
            if (exchangeMeta.IsDefaultExchange)
            {
                return(queue);
            }

            string[] routeKeys = meta.RouteKeys ?? new string[] { };
            if (routeKeys.Length > 0)
            {
                // If route-keys specified, bind the queue to the exchange
                // for each route-key.
                foreach (string routeKey in meta.RouteKeys ?? new string[] {})
                {
                    bus.Bind(exchange, queue, routeKey);
                }
            }
            else
            {
                await bus.BindAsync(exchange, queue, string.Empty);
            }

            return(queue);
        }
예제 #13
0
        /// <summary>
        /// Declare an exchange
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The exchange name</param>
        /// <param name="type">The type of exchange</param>
        /// <param name="durable">Durable exchanges remain active when a server restarts.</param>
        /// <param name="autoDelete">If set, the exchange is deleted when all queues have finished using it.</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The exchange</returns>
        public static Task <IExchange> ExchangeDeclareAsync(
            this IAdvancedBus bus,
            string name,
            string type,
            bool durable    = true,
            bool autoDelete = false,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.ExchangeDeclareAsync(name, c => c.AsDurable(durable).AsAutoDelete(autoDelete).WithType(type), cancellationToken));
        }
예제 #14
0
        private async Task <EasyNetQ.Topology.IExchange> BindExchangeWithMessageQueueAsync(string exchangename)
        {
            _logger.LogDebug("BindExchangeWithMessageQueueAsync() started.");

            var exchange = await _advancedBus.ExchangeDeclareAsync(exchangename, ExchangeType.Topic);

            var queue = await InitializeGetQueuesAsync();

            var binding = await _advancedBus.BindAsync(exchange, queue, string.Empty);

            _logger.LogDebug("BindExchangeWithMessageQueueAsync() completed.");
            return(exchange);
        }
예제 #15
0
        /// <summary>
        /// Declare an exchange
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The exchange name</param>
        /// <param name="configure">The configuration of exchange</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The exchange</returns>
        public static IExchange ExchangeDeclare(
            this IAdvancedBus bus,
            string name,
            Action <IExchangeDeclareConfiguration> configure,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.ExchangeDeclareAsync(name, configure, cancellationToken)
                   .GetAwaiter()
                   .GetResult());
        }
예제 #16
0
        /// <summary>
        /// Declare an exchange
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The exchange name</param>
        /// <param name="type">The type of exchange</param>
        /// <param name="durable">Durable exchanges remain active when a server restarts.</param>
        /// <param name="autoDelete">If set, the exchange is deleted when all queues have finished using it.</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The exchange</returns>
        public static IExchange ExchangeDeclare(
            this IAdvancedBus bus,
            string name,
            string type,
            bool durable    = true,
            bool autoDelete = false,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.ExchangeDeclareAsync(name, type, durable, autoDelete, cancellationToken)
                   .GetAwaiter()
                   .GetResult());
        }
        public async Task <IExchange> DeclareExchangeAsync(string exchangeName, string exchangeType)
        {
            if (exchanges.TryGetValue(exchangeName, out var exchange))
            {
                return(exchange);
            }
            using (await asyncLock.AcquireAsync().ConfigureAwait(false))
            {
                if (exchanges.TryGetValue(exchangeName, out exchange))
                {
                    return(exchange);
                }
                exchange = await advancedBus.ExchangeDeclareAsync(exchangeName, exchangeType).ConfigureAwait(false);

                exchanges[exchangeName] = exchange;
                return(exchange);
            }
        }
예제 #18
0
        public async Task PublishAsync(MessageModel messageAvailable, CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Entering {nameof(PublishAsync)}");

            try
            {
                var exchange = await _advancedBus.ExchangeDeclareAsync(name : _exchanges.ExchangeKey, type : ExchangeType.Direct, cancellationToken : cancellationToken).ConfigureAwait(false);

                var body = new Message <MessageModel>(messageAvailable);
                await _advancedBus.PublishAsync(exchange : exchange, routingKey : _routings.RoutingKey, mandatory : false, message : body, cancellationToken : cancellationToken).ConfigureAwait(false);

                _logger.LogInformation($"Message: {messageAvailable.Text}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }
예제 #19
0
        public async Task DeclareAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Entering {nameof(DeclareAsync)}");

            try
            {
                var exchange = await _advancedBus.ExchangeDeclareAsync(name : _exchanges.ExchangeKey, type : ExchangeType.Direct, cancellationToken : cancellationToken).ConfigureAwait(false);

                var queue = await _advancedBus.QueueDeclareAsync(name : _queues.QueueKey, durable : true, exclusive : false, autoDelete : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                await _advancedBus.BindAsync(exchange : exchange, queue : queue, routingKey : _routings.RoutingKey, headers : null, cancellationToken : cancellationToken).ConfigureAwait(false);

                _logger.LogInformation($"Bind - Exchange: {_exchanges.ExchangeKey}, Queue: {_queues.QueueKey}, RoutingKey: {_routings.RoutingKey}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }
 public async Task<IExchange> DeclareExchangeAsync(IAdvancedBus advancedBus, string exchangeName, string exchangeType)
 {
     IExchange exchange;
     if (exchanges.TryGetValue(exchangeName, out exchange))
     {
         return exchange;
     }
     await semaphore.WaitAsync().ConfigureAwait(false);
     try
     {
         if (exchanges.TryGetValue(exchangeName, out exchange))
         {
             return exchange;
         }
         exchange = await advancedBus.ExchangeDeclareAsync(exchangeName, exchangeType).ConfigureAwait(false);
         exchanges[exchangeName] = exchange;
         return exchange;
     }
     finally
     {
         semaphore.Release();
     }
 }
예제 #21
0
        public async Task SubscribeAsync(Func <string, CancellationToken, Task> processMessageAsync, CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Entering {nameof(SubscribeAsync)}");

            try
            {
                var exchange = await _advancedBus.ExchangeDeclareAsync(name : _exchanges.ExchangeKey, type : ExchangeType.Direct, cancellationToken : cancellationToken).ConfigureAwait(false);

                var queue = await _advancedBus.QueueDeclareAsync(name : _queues.QueueKey, durable : true, exclusive : false, autoDelete : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                await _advancedBus.BindAsync(exchange : exchange, queue : queue, routingKey : _routings.RoutingKey, headers : null, cancellationToken : cancellationToken).ConfigureAwait(false);

                _advancedBus.Consume(queue, (body, _, _) => Task.Factory.StartNew(async() =>
                {
                    var message = Encoding.UTF8.GetString(body);
                    await processMessageAsync(message, cancellationToken).ConfigureAwait(false);
                }, cancellationToken));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }
    public static async Task ResendErrorsAsync(this IAdvancedBus source, string errorQueueName)
    {
        var errorQueue = await source.QueueDeclareAsync(errorQueueName);

        var message = await source.GetMessageAsync(errorQueue);

        while (message != null)
        {
            var utf8Body       = Encoding.UTF8.GetString(message.Body);
            var error          = JsonConvert.DeserializeObject <Error>(utf8Body);
            var errorBodyBytes = Encoding.UTF8.GetBytes(error.Message);
            var exchange       = await source.ExchangeDeclareAsync(error.Exchange, x =>
            {
                // This can be adjusted to fit the exchange actual configuration
                x.AsDurable(true);
                x.AsAutoDelete(false);
                x.WithType("topic");
            });

            await source.PublishAsync(exchange, error.RoutingKey, true, error.BasicProperties, errorBodyBytes);

            message = await source.GetMessageAsync(errorQueue);
        }
    }
예제 #23
0
        private async Task <IExchange> DeclareBusExchangeAsync(CancellationToken cancellationToken)
        {
            var exchangeName = "toxon.micro.bus";

            return(await _bus.ExchangeDeclareAsync(exchangeName, ExchangeType.Direct));
        }
예제 #24
0
 public EasyNetQSubscriberFactory(IBroker broker, string exchangename,
                                  string waitexchangename,
                                  ISubscriberController subscriberController,
                                  IEnvironmentNamingConventionController environmentNamingConventionController,
                                  int retryfactor, IPublisher publisher)
 {
     _broker = broker;
     _bus    = broker.Bus;
     _subscriberController                  = subscriberController;
     _exchange                              = new AsyncLazy <IExchange>(async() => await _bus.ExchangeDeclareAsync(exchangename, ExchangeType.Topic));
     _easyNetQPublisherToWaitExchange       = new EasyNetQPublisher(_bus, waitexchangename, environmentNamingConventionController);
     _environmentNamingConventionController = environmentNamingConventionController;
     _retryfactor                           = retryfactor;
     _publisher                             = publisher;
 }
예제 #25
0
        private async Task <ISubscriptionResult> SubscribeAsyncInternal <T>(
            string subscriptionId,
            Func <T, CancellationToken, Task> onMessage,
            Action <ISubscriptionConfiguration> configure,
            CancellationToken cancellationToken
            )
        {
            using var cts = cancellationToken.WithTimeout(configuration.Timeout);

            var subscriptionConfiguration = new SubscriptionConfiguration(configuration.PrefetchCount);

            configure(subscriptionConfiguration);

            var queueName    = subscriptionConfiguration.QueueName ?? conventions.QueueNamingConvention(typeof(T), subscriptionId);
            var exchangeName = conventions.ExchangeNamingConvention(typeof(T));

            var queue = await advancedBus.QueueDeclareAsync(
                queueName,
                c =>
            {
                c.AsDurable(subscriptionConfiguration.Durable);
                c.AsAutoDelete(subscriptionConfiguration.AutoDelete);
                if (subscriptionConfiguration.Expires.HasValue)
                {
                    c.WithExpires(TimeSpan.FromMilliseconds(subscriptionConfiguration.Expires.Value));
                }
                if (subscriptionConfiguration.MaxPriority.HasValue)
                {
                    c.WithMaxPriority(subscriptionConfiguration.MaxPriority.Value);
                }
                if (subscriptionConfiguration.MaxLength.HasValue)
                {
                    c.WithMaxLength(subscriptionConfiguration.MaxLength.Value);
                }
                if (subscriptionConfiguration.MaxLengthBytes.HasValue)
                {
                    c.WithMaxLengthBytes(subscriptionConfiguration.MaxLengthBytes.Value);
                }
                if (!string.IsNullOrEmpty(subscriptionConfiguration.QueueMode))
                {
                    c.WithQueueMode(subscriptionConfiguration.QueueMode);
                }
            },
                cts.Token
                ).ConfigureAwait(false);

            var exchange = await advancedBus.ExchangeDeclareAsync(exchangeName, ExchangeType.Topic, cancellationToken : cts.Token).ConfigureAwait(false);

            foreach (var topic in subscriptionConfiguration.Topics.DefaultIfEmpty("#"))
            {
                await advancedBus.BindAsync(exchange, queue, topic, cts.Token).ConfigureAwait(false);
            }

            var consumerCancellation = advancedBus.Consume <T>(
                queue,
                (message, messageReceivedInfo) => onMessage(message.Body, default),
                x => x.WithPriority(subscriptionConfiguration.Priority)
                .WithPrefetchCount(subscriptionConfiguration.PrefetchCount)
                .WithExclusive(subscriptionConfiguration.IsExclusive)
                );

            return(new SubscriptionResult(exchange, queue, consumerCancellation));
        }