/// <summary>
        /// StartConsumers - start consumers and connect them to a queue.
        /// </summary>
        /// <param name="consumerName">Consumer name</param>
        /// <param name="retryQueueDetails">Retry queue details if a message needs to be requeued with a delay (a Dead letter exchange must be defined)</param>
        /// <param name="queueName">Queue where the consumers will connect (optional - if not defined, the config value is used)</param>
        /// <param name="totalConsumers">Total consumers to start (optional - if not defined, the config value is used)</param>
        /// <param name="createQueue">Create queue to connect when starting consumers (optional - default is false)</param>
        /// <exception cref="RabbitMQClientException"></exception>
        public void StartConsumers(string consumerName, RetryQueueDetails retryQueueDetails, string queueName = null, byte?totalConsumers = null, bool createQueue = false)
        {
            var config = (IBrokerConfigConsumers)_config;

            var totalConsumersToStart = totalConsumers ?? config.TotalInstances;

            if (totalConsumersToStart <= 0)
            {
                throw new ArgumentException("Invalid total number of consumers to start");
            }

            var triedCreateQueue = false;

            for (var i = 0; i < totalConsumersToStart; i++)
            {
                var routingKeyOrQueueName =
                    string.IsNullOrWhiteSpace(queueName) ? config.RoutingKeyOrQueueName : queueName;

                var totalCreatedConsumers = _consumers.Count;

                var connection = GetConnection(ServiceDescription + "_" + i, totalCreatedConsumers, MaxChannelsPerConnection);

                var channel = connection.CreateModel();

                if (createQueue && !triedCreateQueue)
                {
                    try
                    {
                        RabbitMqUtilities.CreateQueueOrGetInfo(routingKeyOrQueueName, channel);
                        triedCreateQueue = true;
                    }
                    catch (Exception e)
                    {
                        throw new RabbitMqClientException($"Unable do create queue. Details: {e.Message}", e);
                    }
                }

                var consumer = new AsyncEventingBasicConsumerExtended(channel)
                {
                    ConnectedToPort = connection.Endpoint.Port,
                    ConnectedToHost = connection.Endpoint.HostName,
                    ConnectionTime  = DateTime.Now,
                    Id = i,
                    RetentionPeriodInRetryQueueMilliseconds    = retryQueueDetails?.RetentionPeriodInRetryQueueMilliseconds ?? 0,
                    RetentionPeriodInRetryQueueMillisecondsMax = retryQueueDetails?.RetentionPeriodInRetryQueueMillisecondsMax ?? 0,
                    RetryQueue = retryQueueDetails?.RetryQueue
                };

                consumer.Received += Consumer_Received;
                consumer.Shutdown += Consumer_Shutdown;

                var tag = $"{consumerName}_{i}";

                consumer.ConsumerTag = tag;

                _consumers.Add(consumer);

                channel.BasicConsume(routingKeyOrQueueName, false, tag, consumer);
            }
        }
        private void RequeueMessageWithDelay(AsyncEventingBasicConsumerExtended consumer, BasicDeliverEventArgs deliveryArgs, string messageAdditionalInfo)
        {
            if (string.IsNullOrWhiteSpace(consumer.RetryQueue))
            {
                return;
            }

            var properties = consumer.Model.CreateBasicProperties();

            RabbitMqUtilities.SetPropertiesSenderRequeueMessageWithDelay(properties, consumer.RetentionPeriodInRetryQueueMilliseconds, consumer.RetentionPeriodInRetryQueueMillisecondsMax);

            var firstErrorTimeStamp = RabbitMqUtilities.GetFirstErrorTimeStampFromMessageArgs(deliveryArgs.BasicProperties);

            SetFirstErrorTimeStampToProperties(firstErrorTimeStamp, properties);
            SetMessageAdditionalInfoToProperties(messageAdditionalInfo, properties);

            consumer.Model.BasicPublish(
                "",
                consumer.RetryQueue,
                properties,
                deliveryArgs.Body);
        }