/// <summary>
        /// Sends the messages and tracks the send status of each message. Any exceptions are controlled and added to the returned IMessageTracker.
        /// Additionally, this overload provides retries.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="exchange">The exchange to send to</param>
        /// <param name="routingKey">The routing key, empty string is permitted</param>
        /// <param name="messages">A list of objects that will be converted to JSON and sent as individual messages</param>
        /// <param name="retryLimit">The number of retries to perform. If you set it to 3 for example, then up to 4 attempts are made in total</param>
        /// <param name="retryPeriodMs">Milliseconds between each attempt</param>
        /// <param name="messageBatchSize">Publishing will publish this number of messages at a time and then pause and wait for confirmation of delivery. Once an acknowledgement
        /// of each message has been received, or a timeout is reache, the next batch is sent</param>
        /// <param name="safetyPeriod">Adds extra guarantees of correct message send status. Confirms can be received out of order. This means that once all
        /// messages have been sent the channel can be closed prematurely due to incorrect ordering of confirms. The safety period keeps the channel open for an extra period, just in case we
        /// receive more confirms. This safety period is not required when the messageBatchSize is 1</param>
        /// <returns>A message tracker that provides you with the delivery status (to the exchange and queues - not the consumer) information, including errors that may have occurred</returns>
        public async Task <IMessageTracker <T> > SendBatchWithRetryAsync <T>(string exchange,
                                                                             string routingKey,
                                                                             List <T> messages,
                                                                             byte retryLimit,
                                                                             short retryPeriodMs,
                                                                             int messageBatchSize,
                                                                             TimeSpan safetyPeriod)
        {
            var messageTracker = new MessageTracker <T>(messages);

            try
            {
                messageTracker = await SendBatchWithRetryAsync(exchange,
                                                               routingKey,
                                                               messageTracker.GetMessageStates(),
                                                               messageTracker,
                                                               retryLimit,
                                                               retryPeriodMs,
                                                               1,
                                                               messageBatchSize,
                                                               safetyPeriod).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                messageTracker.RegisterUnexpectedException(ex);
            }

            return(messageTracker);
        }
        private async Task <MessageTracker <T> > SendBatchWithRetryAsync <T>(string exchange,
                                                                             string routingKey,
                                                                             List <MessageState <T> > outgoingMessages,
                                                                             MessageTracker <T> messageTracker,
                                                                             byte retryLimit,
                                                                             short retryPeriodMs,
                                                                             byte attempt,
                                                                             int messageBatchSize,
                                                                             TimeSpan safetyPeriod)
        {
            Console.WriteLine("Making attempt #" + attempt);

            try
            {
                await SendBatchAsync(exchange,
                                     routingKey,
                                     outgoingMessages,
                                     messageTracker,
                                     messageBatchSize,
                                     safetyPeriod).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                messageTracker.RegisterUnexpectedException(ex);
            }
            finally
            {
                messageTracker.AssignStatuses();
            }

            if (messageTracker.ShouldRetry() && (attempt - 1) <= retryLimit)
            {
                attempt++;

                Console.WriteLine("Will make attempt #" + attempt + " in " + retryPeriodMs + "ms");
                await Task.Delay(retryPeriodMs).ConfigureAwait(false);

                // delivery tags are reset on a new channel so we need to get a cloned tracker with:
                // - an empty delivert tag dictionary
                // - acknowledgement flag set to false on all message states that we will retry
                // we also get the payloads that can be retried and then do another batch send with just these
                var newMessageTracker = messageTracker.GetCloneWithResetAcknowledgements();
                var retryablePayloads = messageTracker.GetRetryableMessages();

                return(await SendBatchWithRetryAsync(exchange,
                                                     routingKey,
                                                     retryablePayloads,
                                                     newMessageTracker,
                                                     retryLimit,
                                                     retryPeriodMs,
                                                     attempt,
                                                     messageBatchSize,
                                                     safetyPeriod).ConfigureAwait(false));
            }
            else
            {
                return(messageTracker);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Sends the messages and tracks the send status of each message. Any exceptions are controlled and added to the returned IMessageTracker
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="exchange">The exchange to send to</param>
        /// <param name="routingKey">The routing key, empty string is permitted</param>
        /// <param name="messages">A list of objects that will be converted to JSON and sent as individual messages</param>
        /// <param name="messageBatchSize">Publishing will publish this number of messages at a time and then pause and wait for confirmation of delivery. Once an acknowledgement
        /// of each message has been received, or a timeout is reache, the next batch is sent</param>
        /// <param name="safetyPeriod">Adds extra guarantees of correct message send status. Confirms can be received out of order. This means that once all
        /// messages have been sent the channel can be closed prematurely due to incorrect ordering of confirms. The safety period keeps the channel open for an extra period, just in case we
        /// receive more confirms. This safety period is not required when the messageBatchSize is 1</param>
        /// <returns>A message tracker that provides you with the delivery status (to the exchange and queues - not the consumer) information, including errors that may have occurred</returns>
        public IMessageTracker <T> SendMessages <T>(string exchange,
                                                    string routingKey,
                                                    List <T> messages,
                                                    int messageBatchSize)
        {
            var messageTracker = new MessageTracker <T>(messages);

            try
            {
                SendBatch(exchange,
                          routingKey,
                          messageTracker.GetMessageStates(),
                          messageTracker,
                          messageBatchSize);
            }
            catch (Exception ex)
            {
                messageTracker.RegisterUnexpectedException(ex);
            }

            return(messageTracker);
        }