private void CompletePendingMessages(IModel channel, ulong last, bool multiple, bool confirmed) { // Get a list of messages. var highest = PendingMessage.CreateLookupKey(channel.ChannelNumber, last); var lowest = multiple ? PendingMessage.CreateLookupKey(channel.ChannelNumber, ulong.MinValue) : highest; var messages = this.ListPendingMessages(lowest, highest); var status = confirmed ? "Acks" : "Nacks"; if (!messages.Any()) { if (multiple) { this.logger.LogError( "Unknown multiple messages is {Status} with the highest message is {Message}.", status, highest); } else { this.logger.LogError("Unknown message {Message} is {Status}.", highest, status); } return; } // Mark all pending confirmed. foreach (var pending in messages) { this.RemovePendingMessage(pending); pending.SetResult(confirmed); this.logger.LogInformation("Message {Message} is {Status} by the broker.", pending, status); } }
private IEnumerable <PendingMessage> ListPendingMessages(PendingMessage lowest, PendingMessage highest) { lock (this.pendings) { return(this.pendings.GetViewBetween(lowest, highest).ToList()); } }
private void RemovePendingMessage(PendingMessage pending) { lock (this.pendings) { if (!this.pendings.Remove(pending)) { this.logger.LogWarning("Trying to remove non-existent pending message {Message}.", pending); } } }
private void AddPendingMessage(PendingMessage pending) { lock (this.pendings) { if (!this.pendings.Add(pending)) { throw new ArgumentException($"The value {pending} is already exists.", nameof(pending)); } } }
private async Task PublishAsync(IModel channel, IMessage @event, CancellationToken cancellationToken = default) { // Serialize event. var buffer = new ArrayBufferWriter <byte>(); @event.WriteTo(buffer); // Setup message's properties. var props = channel.CreateBasicProperties(); props.DeliveryMode = 2; // persistent props.Type = @event.Descriptor.FullName; props.ContentType = "application/x-protobuf"; // Publish the event. while (true) { var pending = new PendingMessage(channel.ChannelNumber, channel.NextPublishSeqNo); this.AddPendingMessage(pending); try { channel.BasicPublish(this.Options.Exchange, string.Empty, false, props, buffer.WrittenMemory); } catch { this.RemovePendingMessage(pending); throw; } // Wait until confirmed. We don't allowed to cancel here due to the caller don't know if the message is // delivered successfully or not. if (await pending.Completed) { break; } } }