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()); }
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 }; })); }
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()); }
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()); }
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)); } }