Ejemplo n.º 1
0
        public Task PublishAsync <TMessage>(TMessage message, Guid globalMessageId, PublishConfiguration config)
        {
            var context = _contextProvider.GetMessageContext(globalMessageId);
            var props   = _propertiesProvider.GetProperties <TMessage>(config.PropertyModifier + (p => p.Headers.Add(PropertyHeaders.Context, context)));

            Task exchangeTask;

            lock (_topologyLock)
            {
                exchangeTask = _topologyProvider.DeclareExchangeAsync(config.Exchange);
            }
            var channelTask = _channelFactory.GetChannelAsync();

            return(Task
                   .WhenAll(exchangeTask, channelTask)
                   .ContinueWith(t =>
            {
                lock (_publishLock)
                {
                    var ackTask = _acknowledger.GetAckTask(channelTask.Result);
                    channelTask.Result.BasicPublish(
                        exchange: config.Exchange.ExchangeName,
                        routingKey: _config.RouteWithGlobalId ? $"{config.RoutingKey}.{globalMessageId}" : config.RoutingKey,
                        basicProperties: props,
                        body: _serializer.Serialize(message)
                        );
                    return ackTask;
                }
            })
                   .Unwrap());
        }
Ejemplo n.º 2
0
        public Task <ExchangeUpdateResult> UpdateExchangeAsync(ExchangeUpdateConfiguration config)
        {
            var channelTask  = _channelFactory.GetChannelAsync();
            var bindingsTask = _bindingProvider.GetBindingsAsync(config.ExchangeName);

            return(Task
                   .WhenAll(channelTask, bindingsTask)
                   .ContinueWith(t =>
            {
                var channel = channelTask.Result;
                var stopWatch = Stopwatch.StartNew();
                channel.ExchangeDelete(config.ExchangeName);
                channel.ExchangeDeclare(config.ExchangeName, config.ExchangeType.ToString(), config.Durable, config.AutoDelete, config.Arguments);
                foreach (var binding in bindingsTask.Result ?? Enumerable.Empty <Binding>())
                {
                    binding.RoutingKey = config.BindingTransformer(binding.RoutingKey);
                    if (string.Equals(binding.DestinationType, QueueDestination, StringComparison.InvariantCultureIgnoreCase))
                    {
                        channel.QueueBind(binding.Destination, config.ExchangeName, binding.RoutingKey);
                    }
                }
                stopWatch.Stop();
                return new ExchangeUpdateResult
                {
                    Exchange = config,
                    Bindings = bindingsTask.Result,
                    ExecutionTime = stopWatch.Elapsed
                };
            }));
        }
Ejemplo n.º 3
0
 private Task <IRawConsumer> GetOrCreateConsumerAsync(IConsumerConfiguration cfg)
 {
     return(_channelFactory
            .GetChannelAsync()
            .ContinueWith(tChannel =>
     {
         var consumerCs = new ConsumerCompletionSource();
         if (_consumerCompletionSources.TryAdd(tChannel.Result, consumerCs))
         {
             var newConsumer = _consumerFactory.CreateConsumer(cfg, tChannel.Result);
             WireUpConsumer(newConsumer, cfg);
             consumerCs.ConsumerQueues.TryAdd(
                 key: cfg.Queue.FullQueueName,
                 value: newConsumer.Model.BasicConsume(cfg.Queue.FullQueueName, cfg.NoAck, newConsumer)
                 );
             _currentConsumer = consumerCs;
             _logger.LogInformation($"Created consumer on channel '{tChannel.Result.ChannelNumber}' that consumes messages from '{cfg.Queue.FullQueueName}'.");
             consumerCs.TrySetResult(newConsumer);
             return consumerCs.Task;
         }
         _logger.LogDebug($"Consumer for channel '{tChannel.Result.ChannelNumber}' exists. Using it.");
         consumerCs = _consumerCompletionSources[tChannel.Result];
         if (consumerCs.ConsumerQueues.ContainsKey(cfg.Queue.FullQueueName))
         {
             return consumerCs.Task;
         }
         return consumerCs.Task.ContinueWith(t =>
         {
             lock (consumerCs.Consumer)
             {
                 if (consumerCs.ConsumerQueues.ContainsKey(cfg.Queue.FullQueueName))
                 {
                     return t.Result;
                 }
                 consumerCs.ConsumerQueues.TryAdd(
                     key: cfg.Queue.FullQueueName,
                     value: consumerCs.Consumer.Model.BasicConsume(cfg.Queue.FullQueueName, cfg.NoAck, consumerCs.Consumer)
                     );
                 _logger.LogDebug($"Existign consumer for channel '{tChannel.Result.ChannelNumber}' consumes '{cfg.Queue.FullQueueName}'.");
                 return t.Result;
             }
         });
     })
            .Unwrap());
 }
Ejemplo n.º 4
0
        public virtual async Task OnSubscriberExceptionAsync(IRawConsumer consumer, SubscriptionConfiguration config, BasicDeliverEventArgs args, Exception exception)
        {
            if (!config.NoAck)
            {
                consumer.Model.BasicAck(args.DeliveryTag, false);
                consumer.AcknowledgedTags.Add(args.DeliveryTag);
            }
            try
            {
                _logger.LogError($"Error thrown in Subscriber: ", exception);
                _logger.LogDebug($"Attempting to publish message '{args.BasicProperties.MessageId}' to error exchange.");

                await _topologyProvider.DeclareExchangeAsync(_errorExchangeCfg);

                var channel = await _channelFactory.GetChannelAsync();

                var msg             = _serializer.Deserialize(args);
                var actualException = UnwrapInnerException(exception);
                var errorMsg        = new HandlerExceptionMessage
                {
                    Exception = new ExceptionInformation
                    {
                        ExceptionType = actualException.GetType().FullName,
                        InnerMessage  = actualException.InnerException?.Message,
                        Message       = actualException.Message,
                        StackTrace    = actualException.StackTrace
                    },
                    Time    = DateTime.Now,
                    Host    = Environment.MachineName,
                    Message = msg,
                };
                channel.BasicPublish(
                    exchange: _errorExchangeCfg.ExchangeName,
                    routingKey: args.RoutingKey,
                    basicProperties: args.BasicProperties,
                    body: _serializer.Serialize(errorMsg)
                    );
                channel.Close();
            }
            catch (Exception e)
            {
                _logger.LogWarning($"Unable to publish message '{args.BasicProperties.MessageId}' to default error exchange.", e);
            }
        }
        public Task PublishAsync <TMessage>(TMessage message, PublishConfiguration config)
        {
            var props       = _propertiesProvider.GetProperties <TMessage>(config.PropertyModifier);
            var messageId   = props.MessageId;
            var messageType = props.Headers[PropertyHeaders.MessageType];

            Task exchangeTask;

            lock (_topologyLock)
            {
                exchangeTask = _topologyProvider.DeclareExchangeAsync(config.Exchange);
            }
            var channelTask = _channelFactory.GetChannelAsync();

            return(Task
                   .WhenAll(exchangeTask, channelTask)
                   .ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    throw t.Exception;
                }

                channelTask.Result.BasicReturn += config.BasicReturn;

                lock (_publishLock)
                {
                    var ackTask = _acknowledger.GetAckTask(channelTask.Result);
                    channelTask.Result.BasicPublish(
                        exchange: config.Exchange.ExchangeName,
                        routingKey: config.RoutingKey,
                        basicProperties: props,
                        body: _serializer.Serialize(message),
                        mandatory: (config.BasicReturn != null)
                        );
                    _logger.LogDebug($"PublishMessageId:{messageId} MessageType:{messageType}");
                    return ackTask
                    .ContinueWith(a => {
                        channelTask.Result.BasicReturn -= config.BasicReturn;
                    });
                }
            })
                   .Unwrap());
        }
Ejemplo n.º 6
0
        public virtual Task OnSubscriberExceptionAsync(IRawConsumer consumer, SubscriptionConfiguration config, BasicDeliverEventArgs args, Exception exception)
        {
            if (!config.NoAck)
            {
                consumer.Model.BasicAck(args.DeliveryTag, false);
                consumer.AcknowledgedTags.Add(args.DeliveryTag);
            }
            try
            {
                _logger.LogError($"Error thrown in Subscriber: ", exception);
                _logger.LogDebug($"Attempting to publish message '{args.BasicProperties.MessageId}' to error exchange.");

                var topologyTask = _topologyProvider.DeclareExchangeAsync(_errorExchangeCfg);
                var channelTask  = _channelFactory.GetChannelAsync();
                return(Task
                       .WhenAll(topologyTask, channelTask)
                       .ContinueWith(t =>
                {
                    var msg = _serializer.Deserialize(args);
                    var errorMsg = new HandlerExceptionMessage
                    {
                        Exception = exception,
                        Time = DateTime.Now,
                        Host = Environment.MachineName,
                        Message = msg,
                    };
                    channelTask.Result.BasicPublish(
                        exchange: _errorExchangeCfg.ExchangeName,
                        routingKey: args.RoutingKey,
                        basicProperties: args.BasicProperties,
                        body: _serializer.Serialize(errorMsg)
                        );
                    channelTask.Result.Close();
                }));
            }
            catch (Exception e)
            {
                _logger.LogWarning($"Unable to publish message '{args.BasicProperties.MessageId}' to default error exchange.", e);
                return(Task.FromResult(true));
            }
        }