protected virtual Task AckMessageIfApplicable(IPipeContext context) { var autoAck = context.GetConsumeConfiguration()?.AutoAck; if (!autoAck.HasValue) { _logger.Debug("Unable to ack original message. Can not determine if AutoAck is configured."); return(Task.FromResult(0)); } if (autoAck.Value) { _logger.Debug("Consuming in AutoAck mode. No ack'ing will be performed"); return(Task.FromResult(0)); } var deliveryTag = context.GetDeliveryEventArgs()?.DeliveryTag; if (deliveryTag == null) { _logger.Info("Unable to ack original message. Delivery tag not found."); return(Task.FromResult(0)); } var consumerChannel = context.GetConsumer()?.Model; if (consumerChannel != null && consumerChannel.IsOpen && deliveryTag.HasValue) { _logger.Debug("Acking message with {deliveryTag} on channel {channelNumber}", deliveryTag, consumerChannel.ChannelNumber); consumerChannel.BasicAck(deliveryTag.Value, false); } return(Task.FromResult(0)); }
protected virtual Task BindQueueAsync(string queue, string exchange, string routingKey, IPipeContext context, CancellationToken ct) { return(TopologyProvider.BindQueueAsync(queue, exchange, routingKey, context.GetConsumeConfiguration()?.Arguments)); }
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.Info("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 consumeConfiguration = context.GetConsumeConfiguration(); var deadLetterQueueName = GetDeadLetterQueueName(consumeConfiguration.QueueName, retryAck.Span); var retryExchangeName = "default_retry_exchange"; var retryRoutingKey = $"{consumeConfiguration.QueueName}_{consumeConfiguration.RoutingKey}"; await TopologyProvider.DeclareExchangeAsync(new ExchangeDeclaration { Name = retryExchangeName, Durable = true, AutoDelete = true, ExchangeType = ExchangeType.Topic }); await TopologyProvider.BindQueueAsync(consumeConfiguration.QueueName, retryExchangeName, retryRoutingKey); await TopologyProvider.DeclareQueueAsync(new QueueDeclaration { Name = deadLetterQueueName, Durable = true, Arguments = new Dictionary <string, object> { { QueueArgument.DeadLetterExchange, retryExchangeName }, { "x-dead-letter-routing-key", retryRoutingKey }, { QueueArgument.Expires, Convert.ToInt32(retryAck.Span.Add(TimeSpan.FromSeconds(1)).TotalMilliseconds) }, { QueueArgument.MessageTtl, Convert.ToInt32(retryAck.Span.TotalMilliseconds) } } }); await TopologyProvider.BindQueueAsync(deadLetterQueueName, deadLeterExchangeName, retryRoutingKey); using (var publishChannel = await ChannelFactory.CreateChannelAsync(token)) { publishChannel.BasicPublish(deadLeterExchangeName, retryRoutingKey, false, deliveryArgs.BasicProperties, deliveryArgs.Body); } await TopologyProvider.UnbindQueueAsync(deadLetterQueueName, deadLeterExchangeName, retryRoutingKey); context.Properties.AddOrReplace(PipeKey.MessageAcknowledgement, new Ack()); await Next.InvokeAsync(context, token); }