/// <summary> /// Acquires an ackable channel from the channel pool, then publishes message based on the letter/envelope parameters and waits for confirmation. /// <para>Only throws exception when failing to acquire channel or when creating a receipt after the ReceiptBuffer is closed.</para> /// <para>Not fully ready for production yet.</para> /// </summary> /// <param name="message"></param> /// <param name="createReceipt"></param> /// <param name="withOptionalHeaders"></param> public async Task PublishWithConfirmationAsync(IMessage message, bool createReceipt, bool withOptionalHeaders = true) { var error = false; var chanHost = await _channelPool .GetAckChannelAsync() .ConfigureAwait(false); try { chanHost.GetChannel().WaitForConfirmsOrDie(_waitForConfirmation); chanHost .GetChannel() .BasicPublish( message.Envelope.Exchange, message.Envelope.RoutingKey, message.Envelope.RoutingOptions?.Mandatory ?? false, message.BuildProperties(chanHost, withOptionalHeaders), message.GetBodyToPublish(_serializationProvider)); chanHost.GetChannel().WaitForConfirmsOrDie(_waitForConfirmation); } catch (Exception ex) { _logger.LogDebug( LogMessages.Publishers.PublishMessageFailed, $"{message.Envelope.Exchange}->{message.Envelope.RoutingKey}", message.MessageId, ex.Message); error = true; } finally { if (createReceipt) { await CreateReceiptAsync(message, error) .ConfigureAwait(false); } await _channelPool .ReturnChannelAsync(chanHost, error); } }