private void NackCallback <T>(BasicNackEventArgs ea, MessageTracker <T> messageTracker) { if (ea.Multiple) { messageTracker.SetMultipleStatus(ea.DeliveryTag, SendStatus.Failed); } else { messageTracker.SetStatus(ea.DeliveryTag, SendStatus.Failed); } }
private void ReturnedCallback <T>(BasicReturnEventArgs ea, MessageTracker <T> messageTracker) { messageTracker.SetStatus(ea.BasicProperties.MessageId, SendStatus.Unroutable, string.Format("Reply Code: {0} Reply Text: {1}", ea.ReplyCode, ea.ReplyText)); }
private void AckCallback <T>(BasicAckEventArgs ea, MessageTracker <T> messageTracker) { messageTracker.SetStatus(ea.DeliveryTag, SendStatus.Success); }
private async Task SendBatchAsync <T>(string exchange, string routingKey, List <MessageState <T> > messageStates, MessageTracker <T> messageTracker, int messageBatchSize, TimeSpan safetyPeriod) { messageTracker.AttemptsMade++; var factory = new ConnectionFactory() { HostName = "localhost" }; factory.AutomaticRecoveryEnabled = false; using (var connection = factory.CreateConnection()) { using (var channel = connection.CreateModel()) { channel.ConfirmSelect(); channel.BasicAcks += (o, a) => AckCallback(a, messageTracker); channel.BasicNacks += (o, a) => NackCallback(a, messageTracker); channel.BasicReturn += (o, a) => ReturnedCallback(a, messageTracker); channel.ModelShutdown += (o, a) => ModelShutdown(a, messageTracker); int counter = 0; foreach (var messageState in messageStates) { counter++; // create the RabbitMq message from the MessagePayload (the Order class) var messageJson = JsonConvert.SerializeObject(messageState.MessagePayload); var body = Encoding.UTF8.GetBytes(messageJson); var properties = channel.CreateBasicProperties(); properties.Persistent = true; properties.MessageId = messageState.MessageId; properties.Headers = new Dictionary <string, object>(); if (messageState.SendCount > 0) { properties.Headers.Add("republished", true); } // get the next sequence number (delivery tag) and register it with this MessageState object var deliveryTag = channel.NextPublishSeqNo; messageTracker.SetDeliveryTag(deliveryTag, messageState); messageState.Status = SendStatus.PendingResponse; messageState.SendCount++; // send the message try { channel.BasicPublish(exchange: exchange, routingKey: routingKey, basicProperties: properties, body: body, mandatory: true); if (counter % messageBatchSize == 0) { channel.WaitForConfirms(TimeSpan.FromMinutes(1)); } } catch (OperationInterruptedException ex) { if (ex.ShutdownReason.ReplyCode == 404) { messageTracker.SetStatus(messageState.MessageId, SendStatus.NoExchangeFound, ex.Message); } else { messageTracker.SetStatus(messageState.MessageId, SendStatus.Failed, ex.Message); } } catch (Exception ex) { messageTracker.SetStatus(messageState.MessageId, SendStatus.Failed, ex.Message); } if (channel.IsClosed || messageTracker.PublishingInterrupted) { return; } } channel.WaitForConfirms(TimeSpan.FromMinutes(1)); if (safetyPeriod.Ticks > 0) { // add extra buffer in case of out of order last confirm await Task.Delay(safetyPeriod).ConfigureAwait(false); } } } // already disposed exception here }