Esempio n. 1
0
 private static IEnumerable <IModel> CreateSeed(IChannelFactory factory, int channelCount)
 {
     for (var i = 0; i < channelCount; i++)
     {
         yield return(factory.CreateChannelAsync().GetAwaiter().GetResult());
     }
 }
Esempio n. 2
0
        public ISubscription SubscribeAsync <T>(Func <T, TMessageContext, Task> subscribeMethod, SubscriptionConfiguration config)
        {
            var routingKey = _config.RouteWithGlobalId
                                ? $"{config.RoutingKey}.#"
                                : config.RoutingKey;

            var topologyTask = _topologyProvider.BindQueueAsync(config.Queue, config.Exchange, routingKey);
            var channelTask  = _channelFactory.CreateChannelAsync();

            var subscriberTask = Task
                                 .WhenAll(topologyTask, channelTask)
                                 .ContinueWith(t =>
            {
                var consumer            = _consumerFactory.CreateConsumer(config, channelTask.Result);
                consumer.OnMessageAsync = (o, args) => _errorHandling.ExecuteAsync(() =>
                {
                    var body    = _serializer.Deserialize <T>(args.Body);
                    var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]);
                    _contextEnhancer.WireUpContextFeatures(context, consumer, args);
                    return(subscribeMethod(body, context));
                }, exception => _errorHandling.OnSubscriberExceptionAsync(consumer, config, args, exception));
                consumer.Model.BasicConsume(config.Queue.FullQueueName, config.NoAck, consumer);
                _logger.LogDebug($"Setting up a consumer on channel '{channelTask.Result.ChannelNumber}' for queue {config.Queue.QueueName} with NoAck set to {config.NoAck}.");
                return(new Subscription(consumer, config.Queue.QueueName));
            });

            Task.WaitAll(subscriberTask);
            _subscriptions.Add(subscriberTask.Result);
            return(subscriberTask.Result);
        }
        public ISubscription SubscribeAsync <T>(Func <T, Task> subscribeMethod, SubscriptionConfiguration config)
        {
            var routingKey = config.RoutingKey;

            var topologyTask = _topologyProvider.BindQueueAsync(config.Queue, config.Exchange, routingKey);
            var channelTask  = _channelFactory.CreateChannelAsync();

            var subscriberTask = Task
                                 .WhenAll(topologyTask, channelTask)
                                 .ContinueWith(t =>
            {
                if (topologyTask.IsFaulted)
                {
                    throw topologyTask.Exception ?? new Exception("Topology Task Faulted");
                }
                var consumer            = _consumerFactory.CreateConsumer(config, channelTask.Result);
                consumer.OnMessageAsync = async(o, args) =>
                {
                    var body = _serializer.Deserialize <T>(args.Body);
                    await subscribeMethod(body);
                };
                consumer.Model.BasicConsume(config.Queue.FullQueueName, config.NoAck, consumer);
                _logger.LogDebug($"Setting up a consumer on channel '{channelTask.Result.ChannelNumber}' for queue {config.Queue.QueueName} with NoAck set to {config.NoAck}.");
                return(new Subscription(consumer, config.Queue.FullQueueName));
            });

            Task.WaitAll(subscriberTask);
            _subscriptions.Add(subscriberTask.Result);
            return(subscriberTask.Result);
        }
Esempio n. 4
0
        public override async Task <IModel> GetAsync(CancellationToken ct = default(CancellationToken))
        {
            var activeChannels = GetActiveChannelCount();

            if (activeChannels < _options.MinimunPoolSize)
            {
                _logger.Debug("Pool currently has {channelCount}, which is lower than the minimal pool size {minimalPoolSize}. Creating channels.", activeChannels, _options.MinimunPoolSize);
                var delta = _options.MinimunPoolSize - Pool.Count;
                for (var i = 0; i < delta; i++)
                {
                    var channel = await _factory.CreateChannelAsync(ct);

                    Add(channel);
                }
            }

            return(await base.GetAsync(ct));
        }
Esempio n. 5
0
        public ISubscription RespondAsync <TRequest, TResponse>(Func <TRequest, TMessageContext, Task <TResponse> > onMessage, ResponderConfiguration cfg)
        {
            var routingKey   = _config.RouteWithGlobalId ? $"{cfg.RoutingKey}.#" : cfg.RoutingKey;
            var topologyTask = _topologyProvider.BindQueueAsync(cfg.Queue, cfg.Exchange, routingKey);
            var channelTask  = _channelFactory.CreateChannelAsync();

            var respondTask = Task.WhenAll(topologyTask, channelTask)
                              .ContinueWith(t =>
            {
                if (topologyTask.IsFaulted)
                {
                    throw topologyTask.Exception ?? new Exception("Topology Task Fauled");
                }
                var consumer            = _consumerFactory.CreateConsumer(cfg, channelTask.Result);
                consumer.OnMessageAsync = (o, args) => _errorHandling.ExecuteAsync(() =>
                {
                    var body    = _serializer.Deserialize <TRequest>(args.Body);
                    var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]);
                    _contextEnhancer.WireUpContextFeatures(context, consumer, args);

                    return(onMessage(body, context)
                           .ContinueWith(tResponse =>
                    {
                        if (tResponse.IsFaulted)
                        {
                            throw tResponse.Exception ?? new Exception();
                        }
                        if (consumer.AcknowledgedTags.Contains(args.DeliveryTag))
                        {
                            return;
                        }
                        if (tResponse.Result == null)
                        {
                            return;
                        }
                        _logger.LogDebug($"Sending response to request with correlation '{args.BasicProperties.CorrelationId}'.");
                        consumer.Model.BasicPublish(
                            exchange: string.Empty,
                            routingKey: args.BasicProperties.ReplyTo,
                            basicProperties: _propertyProvider.GetProperties <TResponse>(p => p.CorrelationId = args.BasicProperties.CorrelationId),
                            body: _serializer.Serialize(tResponse.Result)
                            );
                    }));
                }, exception => _errorHandling.OnResponseHandlerExceptionAsync(consumer, cfg, args, exception));
                consumer.Model.BasicConsume(cfg.Queue.QueueName, cfg.NoAck, consumer);
                return(new Subscription(consumer, cfg.Queue.QueueName));
            });

            Task.WaitAll(respondTask);
            _subscriptions.Add(respondTask.Result);
            return(respondTask.Result);
        }
        public override async Task InvokeAsync(IPipeContext context, CancellationToken token = default(CancellationToken))
        {
            var ack = GetMessageAcknowledgement(context);

            if (!(ack is Retry retryAck))
            {
                await Next.InvokeAsync(context, token);

                return;
            }

            var deadLeterExchangeName = GetDeadLetterExchangeName(retryAck.Span);
            await TopologyProvider.DeclareExchangeAsync(new ExchangeDeclaration
            {
                Name         = deadLeterExchangeName,
                Durable      = true,
                ExchangeType = ExchangeType.Direct
            });

            var deliveryArgs = GetDeliveryEventArgs(context);

            Logger.LogInformation("Message is marked for Retry. Will be published on exchange {exchangeName} with routing key {routingKey} in {retryIn}", deliveryArgs.Exchange, deliveryArgs.RoutingKey, retryAck.Span);
            UpdateRetryHeaders(deliveryArgs, context);
            var deadLetterQueueName = GetDeadLetterQueueName(deliveryArgs.Exchange, retryAck.Span);
            var deadLetterExchange  = context?.GetConsumerConfiguration()?.Exchange.Name ?? deliveryArgs.Exchange;
            await TopologyProvider.DeclareQueueAsync(new QueueDeclaration
            {
                Name      = deadLetterQueueName,
                Durable   = true,
                Arguments = new Dictionary <string, object>
                {
                    { QueueArgument.DeadLetterExchange, deadLetterExchange },
                    { QueueArgument.Expires, Convert.ToInt32(retryAck.Span.Add(TimeSpan.FromSeconds(1)).TotalMilliseconds) },
                    { QueueArgument.MessageTtl, Convert.ToInt32(retryAck.Span.TotalMilliseconds) }
                }
            });

            await TopologyProvider.BindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers);

            using (var publishChannel = await ChannelFactory.CreateChannelAsync(token))
            {
                publishChannel.BasicPublish(deadLeterExchangeName, deliveryArgs.RoutingKey, false, deliveryArgs.BasicProperties, deliveryArgs.Body);
            }
            await TopologyProvider.UnbindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers);

            context.Properties.AddOrReplace(PipeKey.MessageAcknowledgement, new Ack());
            await Next.InvokeAsync(context, token);
        }
Esempio n. 7
0
        public override async Task <IModel> GetAsync(CancellationToken ct = default(CancellationToken))
        {
            var currentCount = GetActiveChannelCount();

            if (currentCount < _desiredChannelCount)
            {
                var createCount = _desiredChannelCount - currentCount;
                for (var i = 0; i < createCount; i++)
                {
                    var channel = await ChannelFactory.CreateChannelAsync(ct);

                    Add(channel);
                }
            }
            return(await base.GetAsync(ct));
        }
        private void InitializeConsumer()
        {
            var channelTask  = _channelFactory.CreateChannelAsync();
            var topologyTask = _topologyProvider.DeclareQueueAsync(_queueConfig);

            Task.WhenAll(channelTask, topologyTask)
            .ContinueWith(tChannel =>
            {
                _consumer           = new EventingBasicConsumer(channelTask.Result);
                _consumer.Received += (sender, args) =>
                {
                    var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]);
                    var body    = _serializer.Deserialize(args);
                    _messageDispatcher.InvokeMessageHandler(context.GlobalRequestId, body, context);
                    _consumer.Model.BasicAck(args.DeliveryTag, false);
                };
                _consumer.Model.BasicConsume(_queueConfig.FullQueueName, false, _consumer);
            })
            .Wait();
        }
Esempio n. 9
0
 protected virtual Task <IModel> GetOrCreateChannelAsync(CancellationToken token = default(CancellationToken))
 {
     _logger.LogInformation("Creating a dedicated channel for consumer.");
     return(_channelFactory.CreateChannelAsync(token));
 }
 protected virtual Task <IModel> CreateChannelAsync(IPipeContext context, CancellationToken ct)
 {
     return(ChannelFactory.CreateChannelAsync(ct));
 }