private Task SendImpl(RabbitMqMessage message)
        {
            var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            try
            {
                if (_connection.Logger.IsEnabled(LogLevel.Debug))
                {
                    _connection.Logger.LogDebug($"RabbitMqProducer: calling Send.");
                }

                var channel = _connection.Channel;
                if (channel == null)
                {
                    throw new ObjectDisposedException(nameof(RabbitMqProducer));
                }

                var basicProperties = channel.CreateBasicProperties();
                Bind(basicProperties, message);
                basicProperties.MessageId = Guid.NewGuid().ToString();

                _declarationHelper.DeclareExchange(message.Exchange, channel);

                if (message.ShouldConfirmPublish)
                {
                    var seqNo = channel.NextPublishSeqNo;
                    var mif   = new MessageInFlight(tcs, channel, this);
                    this.AddMessageInFlight(mif, TimeSpan.FromSeconds(10));
                }

                channel.BasicPublish(message.Exchange, message.RoutingKey, true, basicProperties, message.Body);

                if (!message.ShouldConfirmPublish)
                {
                    return(Task.CompletedTask);
                }
            }
            catch (Exception ex)
            {
                tcs.SetException(new RabbitMqException("RabbitMqProducer: Send failed!", ex));
            }
            return(tcs.Task);
        }
 internal void RemoveMessageInFlight(MessageInFlight msg)
 {
     //It is normal for the message to not be present, so we are ignoring the return value.
     messagesInFlight.TryRemove(msg.SequenceNumber, out _);
 }
 internal void AddMessageInFlight(MessageInFlight msg, TimeSpan timeout)
 {
     msg.SetupTimeout(timeout);
     messagesInFlight.TryAdd(msg.SequenceNumber, msg);
 }