Beispiel #1
0
        public static async Task <IQueue> GetDelayQueueAsync(this IAdvancedBus advancedBus, string queue)
        {
            // ReSharper disable once InconsistentlySynchronizedField
            if (DelayQueues.TryGetValue(queue, out var result))
            {
                return(result);
            }

            var lockObject = DelayQueueLocks.GetOrAdd(queue, key => new AsyncLock());

            using (await lockObject.AcquireAsync())
            {
                // ReSharper disable once InconsistentlySynchronizedField
                if (DelayQueues.TryGetValue(queue, out result))
                {
                    return(result);
                }

                result = await advancedBus.QueueDeclareAsync(GetDelayQueueName(queue),
                                                             deadLetterExchange : "",
                                                             deadLetterRoutingKey : queue
                                                             );

                lock (DelayQueues)
                {
                    DelayQueues.Add(queue, result);
                }

                return(result);
            }
        }
Beispiel #2
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);
            })));
        }
Beispiel #3
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);
        }
Beispiel #4
0
        public static async Task <IQueue> DeclareMessageBusAsync(this IAdvancedBus advancedBus, MessageBus messageBus)
        {
            if (messageBus.DeadLetterMessageBus == null)
            {
                return(await advancedBus.QueueDeclareAsync(messageBus.Queue));
            }
            else
            {
                await advancedBus.DeclareMessageBusAsync(messageBus.DeadLetterMessageBus);

                return(await advancedBus.QueueDeclareAsync(messageBus.Queue,
                                                           deadLetterExchange : "",
                                                           deadLetterRoutingKey : messageBus.DeadLetterMessageBus.Queue
                                                           ));
            }
        }
        /// <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));
        }
        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);
        }
Beispiel #7
0
        public async Task <IDisposable> AddSubscription <TEvent>(string sourceBoundedContextName,
                                                                 string publishedLanguageEntity)
            where TEvent : class
        {
            var queue = await _messageBus.QueueDeclareAsync(NamingConventions.QueueNamingConvention(_boundedContextName,
                                                                                                    sourceBoundedContextName, publishedLanguageEntity, _subscriberId));

            await _messageBus.BindAsync(
                new Exchange(
                    NamingConventions.ExchangeNamingConvention(sourceBoundedContextName, publishedLanguageEntity)),
                queue, "");

            return(_messageBus.Consume(queue, async(bytes, properties, info) =>
            {
                var msg = Encoding.UTF8.GetString(bytes);

                Console.WriteLine(msg);
                var validationResult = await _schemaValidator.IsValid <TEvent>(msg);
                if (validationResult.IsValid)
                {
                    var envelope = System.Text.Json.JsonSerializer.Deserialize <Envelope <TEvent> >(msg);
                    var props = new MessageProperties();
                    properties.CopyTo(props);
                    await _eventDispatcher.HandleEvent(envelope, props);
                }
                else
                {
                    throw new Exception($"Schema is invalid, errors: {string.Join(", ", validationResult.Errors)}");
                }
            }));
        }
        /// <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 exchange = await exchangeDeclareStrategy.DeclareExchangeAsync(
                conventions.ExchangeNamingConvention(typeof(T)),
                ExchangeType.Topic,
                cts.Token
                ).ConfigureAwait(false);

            var delayString    = delay.ToString(@"dd\_hh\_mm\_ss");
            var futureExchange = await exchangeDeclareStrategy.DeclareExchangeAsync(
                $"{conventions.ExchangeNamingConvention(typeof(T))}_{delayString}",
                ExchangeType.Topic,
                cts.Token
                ).ConfigureAwait(false);

            var futureQueue = await advancedBus.QueueDeclareAsync(
                conventions.QueueNamingConvention(typeof(T), delayString),
                c =>
            {
                c.WithMessageTtl(delay);
                c.WithDeadLetterExchange(exchange);
                if (setDeadLetterRoutingKey)
                {
                    c.WithDeadLetterRoutingKey(topic);
                }
            },
                cts.Token
                ).ConfigureAwait(false);

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

            var properties = new MessageProperties();

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

            var advancedMessage = new Message <T>(message, properties);
            await advancedBus.PublishAsync(
                futureExchange, topic, configuration.MandatoryPublish, advancedMessage, cts.Token
                ).ConfigureAwait(false);
        }
        /// <summary>
        /// Declare a transient server named queue. Note, this queue will only last for duration of the
        /// connection. If there is a connection outage, EasyNetQ will not attempt to recreate
        /// consumers.
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The queue</returns>
        public static IQueue QueueDeclare(this IAdvancedBus bus, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.QueueDeclareAsync(cancellationToken)
                   .GetAwaiter()
                   .GetResult());
        }
        /// <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);
        }
Beispiel #11
0
        /// <summary>
        /// Declare a queue. If the queue already exists this method does nothing
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The name of the queue</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// The queue
        /// </returns>
        public static Task <IQueue> QueueDeclareAsync(
            this IAdvancedBus bus,
            string name,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.QueueDeclareAsync(name, c => { }, cancellationToken));
        }
Beispiel #12
0
        /// <summary>
        /// Declare a queue. If the queue already exists this method does nothing
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The name of the queue</param>
        /// <param name="configure">Delegate to configure the queue</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// The queue
        /// </returns>
        public static IQueue QueueDeclare(
            this IAdvancedBus bus,
            string name,
            Action <IQueueDeclareConfiguration> configure,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.QueueDeclareAsync(name, configure, cancellationToken)
                   .GetAwaiter()
                   .GetResult());
        }
Beispiel #13
0
        /// <summary>
        /// 创建消息队列
        /// </summary>
        /// <param name="adbus"></param>
        /// <param name="queueName"></param>
        /// <returns></returns>
        private async Task <IQueue> CreateQueue <T>(IAdvancedBus adbus)
        {
            var mqInfo = this.GetMqInfo <T>();

            if (adbus == null)
            {
                return(null);
            }
            if (string.IsNullOrEmpty(mqInfo.QueueName))
            {
                return(adbus.QueueDeclare());
            }
            return(await adbus.QueueDeclareAsync(mqInfo.QueueName));
        }
Beispiel #14
0
        /// <summary>
        /// Declare a queue. If the queue already exists this method does nothing
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The name of the queue</param>
        /// <param name="durable">Durable queues remain active when a server restarts.</param>
        /// <param name="exclusive">Exclusive queues may only be accessed by the current connection, and are deleted when that connection closes.</param>
        /// <param name="autoDelete">If set, the queue is deleted when all consumers have finished using it.</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// The queue
        /// </returns>
        public static IQueue QueueDeclare(
            this IAdvancedBus bus,
            string name,
            bool durable,
            bool exclusive,
            bool autoDelete,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.QueueDeclareAsync(name, durable, exclusive, autoDelete, cancellationToken)
                   .GetAwaiter()
                   .GetResult());
        }
Beispiel #15
0
        private async Task <string> SubscribeToReplyAsync(CancellationToken cancellationToken)
        {
            if (_replyQueue != null)
            {
                return(_replyQueue);
            }

            using (await _replyQueueLock.AcquireAsync(cancellationToken))
            {
                if (_replyQueue != null)
                {
                    return(_replyQueue);
                }

                var replyQueue = $"toxon.micro.rpc.reply.{Guid.NewGuid()}";

                var exchange = await _bus.ExchangeDeclareAsync(ReplyExchangeName, ExchangeType.Direct);

                var queue = await _bus.QueueDeclareAsync(replyQueue);

                await _bus.BindAsync(exchange, queue, replyQueue);

                _bus.Consume(queue, (body, props, info) =>
                {
                    var correlationIdString = props.CorrelationId;

                    if (Guid.TryParse(correlationIdString, out var correlationId) && _responseHandlers.TryRemove(correlationId, out var tcs))
                    {
                        tcs.SetResult(MessageHelpers.FromArgs(body, props));
                    }
                });

                _replyQueue = replyQueue;
                return(_replyQueue);
            }
        }
Beispiel #16
0
        /// <summary>
        /// Declare a queue. If the queue already exists this method does nothing
        /// </summary>
        /// <param name="bus">The bus instance</param>
        /// <param name="name">The name of the queue</param>
        /// <param name="durable">Durable queues remain active when a server restarts.</param>
        /// <param name="exclusive">Exclusive queues may only be accessed by the current connection, and are deleted when that connection closes.</param>
        /// <param name="autoDelete">If set, the queue is deleted when all consumers have finished using it.</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// The queue
        /// </returns>
        public static Task <IQueue> QueueDeclareAsync(
            this IAdvancedBus bus,
            string name,
            bool durable,
            bool exclusive,
            bool autoDelete,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(bus, "bus");

            return(bus.QueueDeclareAsync(
                       name,
                       c => c.AsDurable(durable)
                       .AsExclusive(exclusive)
                       .AsAutoDelete(autoDelete),
                       cancellationToken
                       ));
        }
Beispiel #17
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 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);
        }
    }
Beispiel #20
0
        private async Task <EasyNetQ.Topology.IQueue> InitializeGetQueuesAsync()
        {
            _taskQueue ??= await _advancedBus.QueueDeclareAsync(_queueName, maxPriority : byte.MaxValue);

            return(_taskQueue);
        }
Beispiel #21
0
        private async Task <ISubscriber> CreateSubscriberAsync(string name, bool temporary, Action temporaryQueueDisconnected,
                                                               IEnumerable <string> routings, int retrycount, int prefetchcount, bool explicitAcknowledgments, ISubscriptionSelector subscriptionSelector, bool storedeadletter)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException("name argument can not be null or empty");
            }

            if ((routings != null) && (routings.Any(routing => string.IsNullOrEmpty(routing)) || !routings.Any()))
            {
                throw new ArgumentException("routings argument can not be empty or contain empty strings");
            }

            if (retrycount < 0)
            {
                throw new ArgumentException("retrycount argument can not be less than zero");
            }

            if (temporaryQueueDisconnected != null)
            {
                _broker.RegisterDisconnectedAction(temporaryQueueDisconnected);
            }

            //Main subscriber queue and bindings
            var queue = await _bus.QueueDeclareAsync(
                _environmentNamingConventionController.GetQueueName(name), false, true, temporary);

            if (routings != null)
            {
                foreach (var routing in routings)
                {
                    await _bus.BindAsync(await _exchange, queue, routing);
                }
            }

            //Retry subscriber queue and bindings
            for (int i = 1; i <= retrycount; i++)
            {
                var retryqueueroutingkey = _environmentNamingConventionController.GetRetryRoutingKey(name, i);
                var retryqueuequeuename  = _environmentNamingConventionController.GetRetryQueueName(name, i);
                var queueretrybinding    = await _bus.BindAsync(await _exchange, queue,
                                                                retryqueueroutingkey);

                var retryqueue = await _bus.QueueDeclareAsync(retryqueuequeuename,
                                                              false, true, temporary, false, _retryfactor *i, null, null, (await _exchange).Name);

                var retryqueuebinding =
                    await _bus.BindAsync(_easyNetQPublisherToWaitExchange.Exchange,
                                         retryqueue, retryqueueroutingkey);
            }



            //Dead letter subscriber queue and bindings
            if (storedeadletter)
            {
                var deadletterqueueroutingkey = _environmentNamingConventionController
                                                .GetDeadLetterQueueRoutingKey(name);
                var deadletterqueuequeuename = _environmentNamingConventionController.
                                               GetDeadLetterQueueName(name);
                var deadletterqueue = await _bus.QueueDeclareAsync(deadletterqueuequeuename, false, true, temporary);

                var deadletterqueuebinding = await
                                             _bus.BindAsync(_easyNetQPublisherToWaitExchange.Exchange, deadletterqueue,
                                                            deadletterqueueroutingkey);
            }

            //Direct Routing Key binding
            var directroutingkey             = _environmentNamingConventionController.GetDirectRoutingKey(name);
            var queuedirectroutingkeybinding = await _bus.BindAsync(await _exchange, queue,
                                                                    directroutingkey);


            if (_subscriberController.RegisterSubscriberName(name, out IDisposable nameHandle))
            {
                var executionHandler = new ExecutionHandlingStrategy(name, _easyNetQPublisherToWaitExchange,
                                                                     retrycount, _environmentNamingConventionController, explicitAcknowledgments, _publisher, storedeadletter);
                return(new EasyNetQSubscriber(executionHandler, _bus, queue, (ushort)prefetchcount,
                                              subscriptionSelector, executionHandler, nameHandle));
            }
            else
            {
                throw new SubscriberAlreadyExistsException($"The subscriber " +
                                                           $"with name {name}" +
                                                           $" already exists");
            }
        }
Beispiel #22
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));
        }