private async Task RunMessageProcessorAsync() { do { if (CancellationToken.IsCancellationRequested) { break; } if (_receiverLink == null || _receiverLink.IsClosed) { await InitializeAsync().ConfigureAwait(false); } try { using (var message = await _receiverLink.ReceiveAsync(TimeSpan.FromSeconds(10)).ConfigureAwait(false)) { if (message != null) { try { await _messenger.ProcessMessageAsync(Address, (string)message.Body).ConfigureAwait(false); _receiverLink.Accept(message); } catch (RescheduleException) { // no log, this is "wanted" _receiverLink.Release(message); } catch (Exception exception) { Console.WriteLine($"Exception during processing AMQP message, rejecting: {exception}"); _receiverLink.Release(message); } } } } catch (AmqpException e) { if (!CancellationToken.IsCancellationRequested) { Console.WriteLine($"AMQP exception in receiver link for address {Address}: {e}"); } await CloseAsync().ConfigureAwait(false); } } while (!CancellationToken.IsCancellationRequested); // normal end await CloseAsync().ConfigureAwait(false); }
public void Acknowledge(InboundMessageDispatch envelope, AckType ackType) { if (envelope.Message.Facade is AmqpNmsMessageFacade facade) { global::Amqp.Message message = facade.Message; switch (ackType) { case AckType.DELIVERED: envelope.IsDelivered = true; break; case AckType.ACCEPTED: HandleAccepted(envelope, message); break; case AckType.RELEASED: receiverLink.Release(message); RemoveMessage(envelope); break; case AckType.MODIFIED_FAILED_UNDELIVERABLE: receiverLink.Modify(message, true, true); RemoveMessage(envelope); break; default: Tracer.ErrorFormat("Unsupported Ack Type for message: {0}", envelope); throw new ArgumentException($"Unsupported Ack Type for message: {envelope}"); } } else { Tracer.ErrorFormat($"Received Ack for unknown message: {envelope}"); } }
public void ContainerHostMessageSourceTest() { string name = "ContainerHostMessageSourceTest"; int count = 100; Queue <Message> messages = new Queue <Message>(); for (int i = 0; i < count; i++) { messages.Enqueue(new Message("test") { Properties = new Properties() { MessageId = name + i } }); } var source = new TestMessageSource(messages); this.host.RegisterMessageSource(name, source); var connection = new Connection(Address); var session = new Session(connection); var receiver = new ReceiverLink(session, "receiver0", name); int released = 0; int rejected = 0; int ignored = 0; for (int i = 1; i <= count; i++) { Message message = receiver.Receive(); if (i % 5 == 0) { receiver.Reject(message); rejected++; } else if (i % 17 == 0) { receiver.Release(message); released++; } else if (i % 36 == 0) { ignored++; } else { receiver.Accept(message); } } receiver.Close(); session.Close(); connection.Close(); Thread.Sleep(500); Assert.AreEqual(released + ignored, messages.Count, string.Join(",", messages.Select(m => m.Properties.MessageId))); Assert.AreEqual(rejected, source.DeadletterMessage.Count, string.Join(",", source.DeadletterMessage.Select(m => m.Properties.MessageId))); }
public void ContainerHostSourceLinkEndpointTest() { string name = "ContainerHostSourceLinkEndpointTest"; int count = 100; Queue <Message> messages = new Queue <Message>(); for (int i = 0; i < count; i++) { messages.Enqueue(new Message("test") { Properties = new Properties() { MessageId = name + i } }); } var source = new TestMessageSource(messages); this.linkProcessor = new TestLinkProcessor(link => new SourceLinkEndpoint(source, link)); this.host.RegisterLinkProcessor(this.linkProcessor); var connection = new Connection(Address); var session = new Session(connection); var receiver = new ReceiverLink(session, "receiver0", name); int released = 0; int rejected = 0; for (int i = 1; i <= count; i++) { Message message = receiver.Receive(); if (i % 5 == 0) { receiver.Reject(message); rejected++; } else if (i % 17 == 0) { receiver.Release(message); released++; } else { receiver.Accept(message); } } receiver.Close(); session.Close(); connection.Close(); Thread.Sleep(200); Assert.AreEqual(released, messages.Count); Assert.AreEqual(rejected, source.DeadletterMessage.Count); }
public void TestMethod_ReleaseMessage() { string testName = "ReleaseMessage"; const int nMsgs = 20; Connection connection = new Connection(address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, "q1"); for (int i = 0; i < nMsgs; ++i) { Message message = new Message(); message.Properties = new Properties() { MessageId = "msg" + i }; message.ApplicationProperties = new ApplicationProperties(); message.ApplicationProperties["sn"] = i; sender.Send(message, null, null); } ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, "q1"); for (int i = 0; i < nMsgs; ++i) { Message message = receiver.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId); if (i % 2 == 0) { receiver.Accept(message); } else { receiver.Release(message); } } receiver.Close(); ReceiverLink receiver2 = new ReceiverLink(session, "receiver2-" + testName, "q1"); for (int i = 0; i < nMsgs / 2; ++i) { Message message = receiver2.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId); receiver2.Accept(message); } receiver2.Close(); sender.Close(); session.Close(); connection.Close(); }
/// <summary> /// Receive messages from specified azure iothub on specified partition. The MessageManager parses the received message and displays it accordingly /// </summary> /// <param name="partition"></param> /// <param name="offset"></param> /// <param name="msgman"></param> /// <param name="hubData"></param> /// <returns></returns> public static async Task ReceiveMessages(string partition, DateTime offset, MessageManager msgman, IoTAccountData hubData) { string port = hubData.EventHubInfo.EventHubPort.Replace("sb://", ""); port = port.Replace("/", ""); Address address = new Address(port, 5671, hubData.SharedAccessPolicy, hubData.PrimaryKey, "/", "amqps"); Connection connection = await Connection.Factory.CreateAsync(address); Session session = new Session(connection); string totalMilliseconds = ((long)(offset - new DateTime(StartOfEpoch, DateTimeKind.Utc)).TotalMilliseconds).ToString(); Map filters = new Map(); filters.Add(new Amqp.Types.Symbol("apache.org:selector-filter:string"), new DescribedValue( new Amqp.Types.Symbol("apache.org:selector-filter:string"), "amqp.annotation.x-opt-enqueuedtimeutc > " + totalMilliseconds + "")); ReceiverLink receiver = new ReceiverLink(session, "my-receiver", new global::Amqp.Framing.Source() { Address = hubData.EventHubInfo.EventHubEntity + "/ConsumerGroups/$Default/Partitions/" + partition, FilterSet = filters }, null); Amqp.Types.Symbol deviceIdKey = new Amqp.Types.Symbol("iothub-connection-device-id"); string deviceId = hubData.DeviceName; while (true) { Amqp.Message m = await receiver.ReceiveAsync(10000); if (m != null) { var id = m.MessageAnnotations.Map[deviceIdKey].ToString(); if (id == deviceId) { Data data = (Data)m.BodySection; string msg = System.Text.Encoding.UTF8.GetString(data.Binary, 0, data.Binary.Length); bool isValid = msgman.parseMessage(msg); if (isValid) { receiver.Accept(m); } else { receiver.Release(m); } } } } }
public void Acknowledge(InboundMessageDispatch envelope, AckType ackType) { if (envelope.Message.Facade is AmqpNmsMessageFacade facade) { global::Amqp.Message message = facade.Message; switch (ackType) { case AckType.DELIVERED: envelope.IsDelivered = true; break; case AckType.ACCEPTED: AmqpTransactionContext transactionalState = session.TransactionContext; if (transactionalState != null) { receiverLink.Complete(message, transactionalState.GetTxnAcceptState()); transactionalState.RegisterTxConsumer(this); } else { receiverLink.Accept(message); } RemoveMessage(envelope); break; case AckType.RELEASED: receiverLink.Release(message); RemoveMessage(envelope); break; case AckType.MODIFIED_FAILED_UNDELIVERABLE: receiverLink.Modify(message, true, true); RemoveMessage(envelope); break; default: Tracer.Error($"Unsupported Ack Type for message: {envelope.Message}"); throw new ArgumentException($"Unsupported Ack Type for message: {envelope.Message}"); } } else { Tracer.ErrorFormat($"Received Ack for unknown message: {envelope}"); } }
public void TestMethod_MessageDeliveryRelease() { string testName = "MessageDeliveryRelease"; Connection connection = new Connection(testTarget.Address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path); Message message = new Message("msg release"); sender.Send(message, null, null); ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path); message = receiver.Receive(); MessageDelivery messageDelivery = message.GetDelivery(); message.Dispose(); receiver.Release(messageDelivery); connection.Close(); }
public void TransactedRetiring() { if (enabled) { string testName = "TransactedRetiring"; path = "test." + testName; int nMsgs = 10; var ids = new List <string>(); Connection connection = new Connection(address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, path); // send one extra for validation for (int i = 0; i < nMsgs + 1; i++) { Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName }; ids.Add(message.Properties.MessageId); sender.Send(message); } ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, path); Message[] messages = new Message[nMsgs]; for (int i = 0; i < nMsgs; i++) { messages[i] = receiver.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", messages[i].Properties.MessageId); } // commit half using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { for (int i = 0; i < nMsgs / 2; i++) { receiver.Accept(messages[i]); ids.Remove(messages[i].Properties.MessageId); } ts.Complete(); } // rollback using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { for (int i = nMsgs / 2; i < nMsgs; i++) { receiver.Accept(messages[i]); } } // after rollback, messages should be still acquired { Message message = receiver.Receive(); Assert.Contains(message.Properties.MessageId, ids); receiver.Release(message); } // commit using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { for (int i = nMsgs / 2; i < nMsgs; i++) { receiver.Accept(messages[i]); ids.Remove(messages[i].Properties.MessageId); } ts.Complete(); } // only the last message is left { Message message = receiver.Receive(); receiver.Accept(message); ids.Remove(message.Properties.MessageId); } // at this point, the queue should have zero messages. // If there are messages, it is a bug in the broker. Assert.Empty(ids); // shouldn't be any messages left Message empty = receiver.Receive(TimeSpan.Zero); Assert.Null(empty); connection.Close(); } }
public void TransactedRetiringAndPosting() { if (enabled) { string testName = "TransactedRetiringAndPosting"; path = "test." + testName; int nMsgs = 10; var ids = new List <string>(); Connection connection = new Connection(address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, path); for (int i = 0; i < nMsgs; i++) { Message message = new Message("test") { Properties = new Properties() { MessageId = "msg" + i, GroupId = testName } }; ids.Add(message.Properties.MessageId); sender.Send(message); } ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, path); receiver.SetCredit(2, false); Message message1 = receiver.Receive(); Message message2 = receiver.Receive(); // ack message1 and send a new message in a txn using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { receiver.Accept(message1); ids.Remove(message1.Properties.MessageId); Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + nMsgs, GroupId = testName }; ids.Add(message.Properties.MessageId); sender.Send(message); ts.Complete(); } // ack message2 and send a new message in a txn but abort the txn using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { receiver.Accept(message2); Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + (nMsgs + 1), GroupId = testName }; sender.Send(message1); } // release the message, since it shouldn't have been accepted above receiver.Release(message2); // receive all messages. should see the effect of the first txn receiver.SetCredit(nMsgs, false); for (int i = 1; i <= nMsgs; i++) { Message message = receiver.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId); receiver.Accept(message); Assert.Contains(message.Properties.MessageId, ids); ids.Remove(message.Properties.MessageId); } // at this point, the queue should have zero messages. // If there are messages, it is a bug in the broker. Assert.Empty(ids); // shouldn't be any messages left Message empty = receiver.Receive(TimeSpan.Zero); Assert.Null(empty); connection.Close(); } }
public void TransactedRetiringAndPosting() { string testName = "TransactedRetiringAndPosting"; int nMsgs = 10; Connection connection = new Connection(testTarget.Address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path); for (int i = 0; i < nMsgs; i++) { Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName }; sender.Send(message); } ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path); receiver.SetCredit(2, false); Message message1 = receiver.Receive(); Message message2 = receiver.Receive(); // ack message1 and send a new message in a txn using (var ts = new TransactionScope()) { receiver.Accept(message1); Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + nMsgs, GroupId = testName }; sender.Send(message); ts.Complete(); } // ack message2 and send a new message in a txn but abort the txn using (var ts = new TransactionScope()) { receiver.Accept(message2); Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + (nMsgs + 1), GroupId = testName }; sender.Send(message1); } receiver.Release(message2); // receive all messages. should see the effect of the first txn receiver.SetCredit(nMsgs, false); for (int i = 1; i <= nMsgs; i++) { Message message = receiver.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", message.Properties.MessageId); receiver.Accept(message); Assert.AreEqual("msg" + i, message.Properties.MessageId); } connection.Close(); }
public void TransactedRetiring() { string testName = "TransactedRetiring"; int nMsgs = 10; Connection connection = new Connection(testTarget.Address); Session session = new Session(connection); SenderLink sender = new SenderLink(session, "sender-" + testName, testTarget.Path); // send one extra for validation for (int i = 0; i < nMsgs + 1; i++) { Message message = new Message("test"); message.Properties = new Properties() { MessageId = "msg" + i, GroupId = testName }; sender.Send(message); } ReceiverLink receiver = new ReceiverLink(session, "receiver-" + testName, testTarget.Path); Message[] messages = new Message[nMsgs]; for (int i = 0; i < nMsgs; i++) { messages[i] = receiver.Receive(); Trace.WriteLine(TraceLevel.Information, "receive: {0}", messages[i].Properties.MessageId); } // commit half using (var ts = new TransactionScope()) { for (int i = 0; i < nMsgs / 2; i++) { receiver.Accept(messages[i]); } ts.Complete(); } // rollback using (var ts = new TransactionScope()) { for (int i = nMsgs / 2; i < nMsgs; i++) { receiver.Accept(messages[i]); } } // after rollback, messages should be still acquired { Message message = receiver.Receive(); Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId); receiver.Release(message); } // commit using (var ts = new TransactionScope()) { for (int i = nMsgs / 2; i < nMsgs; i++) { receiver.Accept(messages[i]); } ts.Complete(); } // only the last message is left { Message message = receiver.Receive(); Assert.AreEqual("msg" + nMsgs, message.Properties.MessageId); receiver.Accept(message); } // at this point, the queue should have zero messages. // If there are messages, it is a bug in the broker. connection.Close(); }
public static void Main(string[] args) { Trace.TraceLevel = TraceLevel.Frame; Trace.TraceListener = (f, a) => { var t = DateTime.Now.ToString("[hh:ss.fff]") + " " + string.Format(f, a); Console.WriteLine(t); }; connection = new Connection(amqpAddress, null, new Open() { ContainerId = Guid.NewGuid().ToString(), ChannelMax = 64, MaxFrameSize = 200, }, null); connection.Closed = OnClosed; session = new Session(connection); session.Closed = OnClosed; var linkName = Guid.NewGuid().ToString(); senderLink = new SenderLink(session, linkName, new Attach() { Target = new Target() { Address = "TestQueue1", }, //RcvSettleMode = ReceiverSettleMode.Second, //SndSettleMode = SenderSettleMode.Settled, }, null); senderLink.Closed = OnClosed; for (int i = 0; i < 10; i++) { senderLink.Send(CreateMessage(), 5000); } senderLink.Close(); linkName = Guid.NewGuid().ToString(); receiverLink = new ReceiverLink(session, linkName, "TestQueue1"); receiverLink.Closed = OnClosed; receiverLink.SetCredit(1); var message = receiverLink.Receive(20000); int receiveCount = 0; while (message != null) { receiveCount++; //Console.WriteLine(message.Body.GetType()); Console.WriteLine(message.BodySection.GetType()); Console.WriteLine("Receive #{0}. Message = \"{1}\"", receiveCount.ToString(), Encoding.UTF8.GetString(message.GetBody <byte[]>())); if (receiveCount % 7 == 0) { receiverLink.Release(message); } else if (receiveCount % 4 == 0) { receiverLink.Reject(message); } else { receiverLink.Accept(message); } Thread.Sleep(10000); message = receiverLink.Receive(20000); } receiverLink.Close(); session.Close(); connection.Close(); }