public Task SendAsync(ServiceBusMessage[] messages, CancellationToken cancellationToken = default(CancellationToken)) { return(_serviceBusSender.SendMessagesAsync(messages, cancellationToken)); }
public async Task LogsEvents() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { await using var client = GetNoRetryClient(); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.FullyQualifiedNamespace)); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); _listener.EventsById(ServiceBusEventSource.ClientCreateStartEvent).Where(e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.FullyQualifiedNamespace) && e.Payload.Contains(sender.EntityPath)); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchCompleteEvent, e => e.Payload.Contains(sender.Identifier)); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkCompleteEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.SendMessageStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.SendMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier)); Assert.That( async() => await client.CreateSessionReceiverAsync(scope.QueueName), Throws.InstanceOf <InvalidOperationException>()); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace) && e.Payload.Contains(scope.QueueName)); _listener.SingleEventById(ServiceBusEventSource.ClientCreateExceptionEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace) && e.Payload.Contains(scope.QueueName)); var receiver = client.CreateReceiver(scope.QueueName); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace)); var messageEnum = messages.GetEnumerator(); var remainingMessages = messageCount; while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(item.DeliveryCount, 1); } } _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkCompleteEvent, e => e.Payload.Contains(receiver.Identifier)); Assert.IsTrue(_listener.EventsById(ServiceBusEventSource.ReceiveMessageStartEvent).Any()); Assert.IsTrue(_listener.EventsById(ServiceBusEventSource.ReceiveMessageCompleteEvent).Any()); Assert.AreEqual(0, remainingMessages); messageEnum.Reset(); foreach (var item in await receiver.PeekMessagesAsync(messageCount)) { messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); } _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkStartEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkCompleteEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.PeekMessageStartEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.PeekMessageCompleteEvent, e => e.Payload.Contains(receiver.Identifier)); var seq = await sender.ScheduleMessageAsync(new ServiceBusMessage(), DateTimeOffset.UtcNow.AddMinutes(1)); _listener.SingleEventById(ServiceBusEventSource.ScheduleMessageStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ScheduleMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier)); await sender.CancelScheduledMessageAsync(seq); _listener.SingleEventById(ServiceBusEventSource.CancelScheduledMessageStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CancelScheduledMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier)); await receiver.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier)); // link closed event is fired asynchronously, so add a small delay await Task.Delay(TimeSpan.FromSeconds(5)); _listener.SingleEventById(ServiceBusEventSource.ReceiveLinkClosedEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ManagementLinkClosedEvent, e => e.Payload.Contains(receiver.Identifier)); Assert.IsFalse(_listener.EventsById(ServiceBusEventSource.MaxMessagesExceedsPrefetchEvent).Any()); receiver = client.CreateReceiver(scope.QueueName, new ServiceBusReceiverOptions { PrefetchCount = 10 }); await receiver.ReceiveMessagesAsync(20, TimeSpan.FromSeconds(1)); _listener.SingleEventById(ServiceBusEventSource.MaxMessagesExceedsPrefetchEvent, e => e.Payload.Contains(receiver.Identifier)); await sender.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier)); await client.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier)); } }
public async Task SenderReceiverActivities(bool useSessions) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: useSessions)) { using var listener = new TestDiagnosticListener(EntityScopeFactory.DiagnosticNamespace); var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); string sessionId = null; if (useSessions) { sessionId = "sessionId"; } int numMessages = 5; var msgs = GetMessages(numMessages, sessionId); await sender.SendMessagesAsync(msgs); Activity[] sendActivities = AssertSendActivities(useSessions, sender, msgs, listener); ServiceBusReceiver receiver = null; if (useSessions) { receiver = await client.CreateSessionReceiverAsync(scope.QueueName); } else { receiver = client.CreateReceiver(scope.QueueName); } var remaining = numMessages; List <ServiceBusReceivedMessage> receivedMsgs = new List <ServiceBusReceivedMessage>(); while (remaining > 0) { // loop in case we don't receive all messages in one attempt var received = await receiver.ReceiveMessagesAsync(remaining); receivedMsgs.AddRange(received); (string Key, object Value, DiagnosticListener)receiveStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Start", receiveStart.Key); Activity receiveActivity = (Activity)receiveStart.Value; AssertCommonTags(receiveActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.RequestedMessageCountAttribute, remaining.ToString())); CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.MessageIdAttribute, string.Join(",", received.Select(m => m.MessageId).ToArray()))); remaining -= received.Count; if (useSessions) { CollectionAssert.Contains( receiveActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, string.Join(",", msgs.Select(m => m.SessionId).Distinct().ToArray()))); } var receiveLinkedActivities = ((IEnumerable <Activity>)receiveActivity.GetType().GetProperty("Links").GetValue(receiveActivity)).ToArray(); for (int i = 0; i < receiveLinkedActivities.Length; i++) { Assert.AreEqual(sendActivities[i].ParentId, receiveLinkedActivities[i].ParentId); } (string Key, object Value, DiagnosticListener)receiveStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveActivityName + ".Stop", receiveStop.Key); } var msgIndex = 0; var completed = receivedMsgs[msgIndex]; await receiver.CompleteMessageAsync(completed); (string Key, object Value, DiagnosticListener)completeStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Start", completeStart.Key); Activity completeActivity = (Activity)completeStart.Value; AssertCommonTags(completeActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(completeActivity, completed.LockToken); (string Key, object Value, DiagnosticListener)completeStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CompleteActivityName + ".Stop", completeStop.Key); var deferred = receivedMsgs[++msgIndex]; await receiver.DeferMessageAsync(deferred); (string Key, object Value, DiagnosticListener)deferStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Start", deferStart.Key); Activity deferActivity = (Activity)deferStart.Value; AssertCommonTags(deferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(deferActivity, deferred.LockToken); (string Key, object Value, DiagnosticListener)deferStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeferActivityName + ".Stop", deferStop.Key); var deadLettered = receivedMsgs[++msgIndex]; await receiver.DeadLetterMessageAsync(deadLettered); (string Key, object Value, DiagnosticListener)deadLetterStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Start", deadLetterStart.Key); Activity deadLetterActivity = (Activity)deadLetterStart.Value; AssertCommonTags(deadLetterActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(deadLetterActivity, deadLettered.LockToken); (string Key, object Value, DiagnosticListener)deadletterStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.DeadLetterActivityName + ".Stop", deadletterStop.Key); var abandoned = receivedMsgs[++msgIndex]; await receiver.AbandonMessageAsync(abandoned); (string Key, object Value, DiagnosticListener)abandonStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Start", abandonStart.Key); Activity abandonActivity = (Activity)abandonStart.Value; AssertCommonTags(abandonActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(abandonActivity, abandoned.LockToken); (string Key, object Value, DiagnosticListener)abandonStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.AbandonActivityName + ".Stop", abandonStop.Key); var receiveDeferMsg = await receiver.ReceiveDeferredMessageAsync(deferred.SequenceNumber); (string Key, object Value, DiagnosticListener)receiveDeferStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Start", receiveDeferStart.Key); Activity receiveDeferActivity = (Activity)receiveDeferStart.Value; AssertCommonTags(receiveDeferActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( receiveDeferActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.MessageIdAttribute, deferred.MessageId)); CollectionAssert.Contains( receiveDeferActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SequenceNumbersAttribute, deferred.SequenceNumber.ToString())); (string Key, object Value, DiagnosticListener)receiveDeferStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ReceiveDeferredActivityName + ".Stop", receiveDeferStop.Key); // renew lock if (useSessions) { var sessionReceiver = (ServiceBusSessionReceiver)receiver; await sessionReceiver.RenewSessionLockAsync(); (string Key, object Value, DiagnosticListener)renewStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Start", renewStart.Key); Activity renewActivity = (Activity)renewStart.Value; AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); CollectionAssert.Contains( renewActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)renewStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewSessionLockActivityName + ".Stop", renewStop.Key); // set state var state = Encoding.UTF8.GetBytes("state"); await sessionReceiver.SetSessionStateAsync(state); (string Key, object Value, DiagnosticListener)setStateStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Start", setStateStart.Key); Activity setStateActivity = (Activity)setStateStart.Value; AssertCommonTags(setStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); CollectionAssert.Contains( setStateActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)setStateStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.SetSessionStateActivityName + ".Stop", setStateStop.Key); // get state var getState = await sessionReceiver.GetSessionStateAsync(); Assert.AreEqual(state, getState); (string Key, object Value, DiagnosticListener)getStateStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Start", getStateStart.Key); Activity getStateActivity = (Activity)getStateStart.Value; AssertCommonTags(getStateActivity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); CollectionAssert.Contains( getStateActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.SessionIdAttribute, "sessionId")); (string Key, object Value, DiagnosticListener)getStateStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.GetSessionStateActivityName + ".Stop", getStateStop.Key); } else { await receiver.RenewMessageLockAsync(receivedMsgs[4]); (string Key, object Value, DiagnosticListener)renewStart = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Start", renewStart.Key); Activity renewActivity = (Activity)renewStart.Value; AssertCommonTags(renewActivity, receiver.EntityPath, receiver.FullyQualifiedNamespace); AssertLockTokensTag(renewActivity, receivedMsgs[4].LockToken); CollectionAssert.Contains( renewActivity.Tags, new KeyValuePair <string, string>( DiagnosticProperty.LockedUntilAttribute, receivedMsgs[4].LockedUntil.ToString())); (string Key, object Value, DiagnosticListener)renewStop = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.RenewMessageLockActivityName + ".Stop", renewStop.Key); } // schedule msgs = GetMessages(numMessages, sessionId); foreach (var msg in msgs) { var seq = await sender.ScheduleMessageAsync(msg, DateTimeOffset.UtcNow.AddMinutes(1)); Assert.IsNotNull(msg.Properties[DiagnosticProperty.DiagnosticIdAttribute]); (string Key, object Value, DiagnosticListener)startMessage = listener.Events.Dequeue(); Activity messageActivity = (Activity)startMessage.Value; AssertCommonTags(messageActivity, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Start", startMessage.Key); (string Key, object Value, DiagnosticListener)stopMessage = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.MessageActivityName + ".Stop", stopMessage.Key); (string Key, object Value, DiagnosticListener)startSchedule = listener.Events.Dequeue(); AssertCommonTags((Activity)startSchedule.Value, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Start", startSchedule.Key); (string Key, object Value, DiagnosticListener)stopSchedule = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.ScheduleActivityName + ".Stop", stopSchedule.Key); var linkedActivities = ((IEnumerable <Activity>)startSchedule.Value.GetType().GetProperty("Links").GetValue(startSchedule.Value)).ToArray(); Assert.AreEqual(1, linkedActivities.Length); Assert.AreEqual(messageActivity.Id, linkedActivities[0].ParentId); await sender.CancelScheduledMessageAsync(seq); (string Key, object Value, DiagnosticListener)startCancel = listener.Events.Dequeue(); AssertCommonTags((Activity)startCancel.Value, sender.EntityPath, sender.FullyQualifiedNamespace); Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Start", startCancel.Key); (string Key, object Value, DiagnosticListener)stopCancel = listener.Events.Dequeue(); Assert.AreEqual(DiagnosticProperty.CancelActivityName + ".Stop", stopCancel.Key); } // send a batch var batch = await sender.CreateMessageBatchAsync(); for (int i = 0; i < numMessages; i++) { batch.TryAddMessage(GetMessage(sessionId)); } await sender.SendMessagesAsync(batch); AssertSendActivities(useSessions, sender, batch.AsEnumerable <ServiceBusMessage>(), listener); }; }
static async Task SendMessageBatchAsync() { // create a Service Bus client await using (ServiceBusClient client = new ServiceBusClient(connectionString)) { // create a sender for the queue ServiceBusSender sender = client.CreateSender(queueName); // get the messages to be sent to the Service Bus queue Queue<ServiceBusMessage> messages = CreateMessages(); // total number of messages to be sent to the Service Bus queue int messageCount = messages.Count; // while all messages are not sent to the Service Bus queue while (messages.Count > 0) { // start a new batch using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); // add the first message to the batch if (messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue once the message is added to the batch messages.Dequeue(); } else { // if the first message can't fit, then it is too large for the batch throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent."); } // add as many messages as possible to the current batch while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue as it has been added to the batch messages.Dequeue(); } // now, send the batch await sender.SendMessagesAsync(messageBatch); // if there are any remaining messages in the .NET queue, the while loop repeats } Console.WriteLine($"Sent a batch of {messageCount} messages to the topic: {queueName}"); } }
public async Task LogsSessionEvents() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = GetNoRetryClient(); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.FullyQualifiedNamespace)); var messageCount = 10; ServiceBusSender sender = client.CreateSender(scope.QueueName); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.FullyQualifiedNamespace) && e.Payload.Contains(sender.EntityPath)); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateMessageBatchCompleteEvent, e => e.Payload.Contains(sender.Identifier)); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, "sessionId").AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateSendLinkCompleteEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.SendMessageStartEvent, e => e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.SendMessageCompleteEvent, e => e.Payload.Contains(sender.Identifier)); var receiver = client.CreateReceiver(scope.QueueName); _listener.SingleEventById(ServiceBusEventSource.ClientCreateStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace)); // can't use a non-session receiver for session queue Assert.That( async() => await receiver.ReceiveMessageAsync(), Throws.InstanceOf <InvalidOperationException>()); _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkExceptionEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageStartEvent, e => e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageExceptionEvent, e => e.Payload.Contains(receiver.Identifier)); var sessionReceiver = await client.CreateSessionReceiverAsync(scope.QueueName); _listener.EventsById(ServiceBusEventSource.ClientCreateStartEvent).Where(e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(client.FullyQualifiedNamespace)).Any(); _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateReceiveLinkCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); var msg = await sessionReceiver.ReceiveMessageAsync(); _listener.SingleEventById(ServiceBusEventSource.ReceiveMessageStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); msg = await sessionReceiver.PeekMessageAsync(); _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.CreateManagementLinkCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.PeekMessageStartEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.PeekMessageCompleteEvent, e => e.Payload.Contains(sessionReceiver.Identifier)); await receiver.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusReceiver)) && e.Payload.Contains(receiver.Identifier)); await sessionReceiver.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(sessionReceiver.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSessionReceiver)) && e.Payload.Contains(sessionReceiver.Identifier)); await Task.Delay(TimeSpan.FromSeconds(2)); _listener.SingleEventById(ServiceBusEventSource.ReceiveLinkClosedEvent, e => e.Payload.Contains(sessionReceiver.Identifier) && e.Payload.Contains(sessionReceiver.SessionId)); await sender.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusSender)) && e.Payload.Contains(sender.Identifier)); await client.DisposeAsync(); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeStartEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier)); _listener.SingleEventById(ServiceBusEventSource.ClientDisposeCompleteEvent, e => e.Payload.Contains(nameof(ServiceBusClient)) && e.Payload.Contains(client.Identifier)); } }
public async Task ProcessMessages() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; await using var client = GetClient(); #region Snippet:ServiceBusProcessMessages //@@ string connectionString = "<connection_string>"; //@@ string queueName = "<queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" //@@ await using var client = new ServiceBusClient(connectionString); // create the sender ServiceBusSender sender = client.CreateSender(queueName); // create a message batch that we can send ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); messageBatch.TryAddMessage(new ServiceBusMessage(Encoding.UTF8.GetBytes("First"))); messageBatch.TryAddMessage(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second"))); // send the message batch await sender.SendMessagesAsync(messageBatch); // get the options to use for configuring the processor var options = new ServiceBusProcessorOptions { // By default after the message handler returns, the processor will complete the message // If I want more fine-grained control over settlement, I can set this to false. AutoCompleteMessages = false, // I can also allow for multi-threading MaxConcurrentCalls = 2 }; // create a processor that we can use to process the messages ServiceBusProcessor processor = client.CreateProcessor(queueName, options); // since the message handler will run in a background thread, in order to prevent // this sample from terminating immediately, we can use a task completion source that // we complete from within the message handler. TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler; async Task MessageHandler(ProcessMessageEventArgs args) { string body = args.Message.Body.ToString(); Console.WriteLine(body); // we can evaluate application logic and use that to determine how to settle the message. await args.CompleteMessageAsync(args.Message); tcs.SetResult(true); } Task ErrorHandler(ProcessErrorEventArgs args) { // the error source tells me at what point in the processing an error occurred Console.WriteLine(args.ErrorSource); // the fully qualified namespace is available Console.WriteLine(args.FullyQualifiedNamespace); // as well as the entity path Console.WriteLine(args.EntityPath); Console.WriteLine(args.Exception.ToString()); return(Task.CompletedTask); } await processor.StartProcessingAsync(); // await our task completion source task so that the message handler will be invoked at least once. await tcs.Task; // stop processing once the task completion source was completed. await processor.StopProcessingAsync(); #endregion } }
public async Task SenderReceiverActivities(bool useSessions) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: useSessions)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); string sessionId = null; if (useSessions) { sessionId = "sessionId"; } int numMessages = 5; var msgs = ServiceBusTestUtilities.GetMessages(numMessages, sessionId); await sender.SendMessagesAsync(msgs); Activity[] sendActivities = AssertSendActivities(useSessions, sender, msgs); ServiceBusReceiver receiver = null; if (useSessions) { receiver = await client.AcceptNextSessionAsync(scope.QueueName); } else { receiver = client.CreateReceiver(scope.QueueName); } var remaining = numMessages; List <ServiceBusReceivedMessage> receivedMsgs = new List <ServiceBusReceivedMessage>(); while (remaining > 0) { // loop in case we don't receive all messages in one attempt var received = await receiver.ReceiveMessagesAsync(remaining); receivedMsgs.AddRange(received); var receiveScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveActivityName); AssertCommonTags(receiveScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); var receiveLinkedActivities = receiveScope.LinkedActivities; for (int i = 0; i < receiveLinkedActivities.Count; i++) { Assert.AreEqual(sendActivities[i].ParentId, receiveLinkedActivities[i].ParentId); } remaining -= received.Count; } var msgIndex = 0; var completed = receivedMsgs[msgIndex]; await receiver.CompleteMessageAsync(completed); var completeScope = _listener.AssertAndRemoveScope(DiagnosticProperty.CompleteActivityName); AssertCommonTags(completeScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); var deferred = receivedMsgs[++msgIndex]; await receiver.DeferMessageAsync(deferred); var deferredScope = _listener.AssertAndRemoveScope(DiagnosticProperty.DeferActivityName); AssertCommonTags(deferredScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); var deadLettered = receivedMsgs[++msgIndex]; await receiver.DeadLetterMessageAsync(deadLettered); var deadLetterScope = _listener.AssertAndRemoveScope(DiagnosticProperty.DeadLetterActivityName); AssertCommonTags(deadLetterScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); var abandoned = receivedMsgs[++msgIndex]; await receiver.AbandonMessageAsync(abandoned); var abandonScope = _listener.AssertAndRemoveScope(DiagnosticProperty.AbandonActivityName); AssertCommonTags(abandonScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); var receiveDeferMsg = await receiver.ReceiveDeferredMessageAsync(deferred.SequenceNumber); var receiveDeferScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveDeferredActivityName); AssertCommonTags(receiveDeferScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); // renew lock if (useSessions) { var sessionReceiver = (ServiceBusSessionReceiver)receiver; await sessionReceiver.RenewSessionLockAsync(); var renewSessionScope = _listener.AssertAndRemoveScope(DiagnosticProperty.RenewSessionLockActivityName); AssertCommonTags(renewSessionScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); // set state var state = new BinaryData("state"); await sessionReceiver.SetSessionStateAsync(state); var setStateScope = _listener.AssertAndRemoveScope(DiagnosticProperty.SetSessionStateActivityName); AssertCommonTags(setStateScope.Activity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); // get state var getState = await sessionReceiver.GetSessionStateAsync(); Assert.AreEqual(state.ToArray(), getState.ToArray()); var getStateScope = _listener.AssertAndRemoveScope(DiagnosticProperty.GetSessionStateActivityName); AssertCommonTags(getStateScope.Activity, sessionReceiver.EntityPath, sessionReceiver.FullyQualifiedNamespace); } else { await receiver.RenewMessageLockAsync(receivedMsgs[4]); var renewMessageScope = _listener.AssertAndRemoveScope(DiagnosticProperty.RenewMessageLockActivityName); AssertCommonTags(renewMessageScope.Activity, receiver.EntityPath, receiver.FullyQualifiedNamespace); } // schedule msgs = ServiceBusTestUtilities.GetMessages(numMessages, sessionId); foreach (var msg in msgs) { var seq = await sender.ScheduleMessageAsync(msg, DateTimeOffset.UtcNow.AddMinutes(1)); Assert.IsNotNull(msg.ApplicationProperties[DiagnosticProperty.DiagnosticIdAttribute]); var messageScope = _listener.AssertAndRemoveScope(DiagnosticProperty.MessageActivityName); AssertCommonTags(messageScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace); var scheduleScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ScheduleActivityName); AssertCommonTags(scheduleScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace); var linkedActivities = scheduleScope.LinkedActivities; Assert.AreEqual(1, linkedActivities.Count); Assert.AreEqual(messageScope.Activity.Id, linkedActivities[0].ParentId); await sender.CancelScheduledMessageAsync(seq); var cancelScope = _listener.AssertAndRemoveScope(DiagnosticProperty.CancelActivityName); AssertCommonTags(cancelScope.Activity, sender.EntityPath, sender.FullyQualifiedNamespace); } // send a batch var batch = await sender.CreateMessageBatchAsync(); for (int i = 0; i < numMessages; i++) { batch.TryAddMessage(ServiceBusTestUtilities.GetMessage(sessionId)); } await sender.SendMessagesAsync(batch); AssertSendActivities(useSessions, sender, batch.AsEnumerable <ServiceBusMessage>()); }; }
public async Task MaxAutoLockRenewalDurationRespected(int numThreads, int autoLockRenewalDuration) { var lockDuration = TimeSpan.FromSeconds(5); await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = GetClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoCompleteMessages = false, MaxAutoLockRenewalDuration = TimeSpan.FromSeconds(autoLockRenewalDuration) }; await using var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { var message = args.Message; // wait 2x lock duration in case the // lock was renewed already await Task.Delay(lockDuration.Add(lockDuration)); var lockedUntil = message.LockedUntil; if (!args.CancellationToken.IsCancellationRequested) { // only do the assertion if cancellation wasn't requested as otherwise // the exception we would get is a TaskCanceledException rather than ServiceBusException Assert.AreEqual(lockedUntil, message.LockedUntil); Assert.That( async() => await args.CompleteMessageAsync(message, args.CancellationToken), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusFailureReason.MessageLockLost)); Interlocked.Increment(ref messageCt); var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); await processor.StopProcessingAsync(); Assert.AreEqual(numThreads, messageCt); } }
public async Task UserSettlingWithAutoCompleteDoesNotThrow(int numThreads) { await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); // use double the number of threads so we can make sure we test that we don't // retrieve more messages than expected when there are more messages available using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads * 2; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoCompleteMessages = true, MaxReceiveWaitTime = TimeSpan.FromSeconds(30) }; await using var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { try { var message = args.Message; switch (numThreads) { case 1: await args.CompleteMessageAsync(message, args.CancellationToken); break; case 5: await args.AbandonMessageAsync(message); break; case 10: await args.DeadLetterMessageAsync(message); break; case 20: await args.DeferMessageAsync(message); break; } Interlocked.Increment(ref messageCt); } finally { var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); await processor.StopProcessingAsync(); // we complete each task after one message being processed, so the total number of messages // processed should equal the number of threads, but it's possible that we may process a few more per thread. Assert.IsTrue(messageCt >= numThreads); Assert.IsTrue(messageCt <= messageSendCt, messageCt.ToString()); } }
public async Task MaxAutoLockRenewalDurationRespected(int numThreads, int autoLockRenewalDuration) { var lockDuration = ShortLockDuration; await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = CreateClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = ServiceBusTestUtilities.AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoCompleteMessages = false, MaxAutoLockRenewalDuration = TimeSpan.FromSeconds(autoLockRenewalDuration) }; await using var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ServiceBusTestUtilities.ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { var message = args.Message; // wait until 5 seconds past the locked until time await Task.Delay(message.LockedUntil.Subtract(DateTimeOffset.UtcNow).Add(TimeSpan.FromSeconds(5))); var lockedUntil = message.LockedUntil; if (!args.CancellationToken.IsCancellationRequested) { // only do the assertion if cancellation wasn't requested as otherwise // the exception we would get is a TaskCanceledException rather than ServiceBusException Assert.AreEqual(lockedUntil, message.LockedUntil); ServiceBusException exception = await AsyncAssert.ThrowsAsync <ServiceBusException>( async() => await args.CompleteMessageAsync(message, args.CancellationToken)); Assert.AreEqual(ServiceBusFailureReason.MessageLockLost, exception.Reason); Interlocked.Increment(ref messageCt); var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); await processor.StopProcessingAsync(); // greater or equal because the same message may be received multiple times Assert.GreaterOrEqual(messageCt, numThreads); } }
public async Task AutoLockRenewalWorks(int numThreads) { var lockDuration = TimeSpan.FromSeconds(10); await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = GetClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoCompleteMessages = false }; await using var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += args => { // If the connection drops due to network flakiness // after the message is received but before we // complete it, we will get a message lock // lost exception. We are still able to verify // that the message will be completed eventually. var exception = (ServiceBusException)args.Exception; if (!(args.Exception is ServiceBusException sbEx) || sbEx.Reason != ServiceBusFailureReason.MessageLockLost) { Assert.Fail(args.Exception.ToString()); } return(Task.CompletedTask); }; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { var message = args.Message; var lockedUntil = message.LockedUntil; await Task.Delay(lockDuration); await args.CompleteMessageAsync(message, args.CancellationToken); Interlocked.Increment(ref messageCt); var setIndex = Interlocked.Increment(ref completionSourceIndex); completionSources[setIndex].SetResult(true); } await Task.WhenAll(completionSources.Select(source => source.Task)); Assert.IsTrue(processor.IsProcessing); await processor.StopProcessingAsync(); Assert.IsFalse(processor.IsProcessing); Assert.AreEqual(numThreads, messageCt); } }
public async Task ProcessMessages(int numThreads, bool autoComplete) { await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false)) { await using var client = CreateClient(60); ServiceBusSender sender = client.CreateSender(scope.QueueName); // use double the number of threads so we can make sure we test that we don't // retrieve more messages than expected when there are more messages available using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads * 2; ServiceBusMessageBatch messageBatch = ServiceBusTestUtilities.AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoCompleteMessages = autoComplete, PrefetchCount = 20 }; await using var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ServiceBusTestUtilities.ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { try { var message = args.Message; if (!autoComplete) { await args.CompleteMessageAsync(message, args.CancellationToken); } Interlocked.Increment(ref messageCt); } finally { var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); var start = DateTime.UtcNow; await processor.StopProcessingAsync(); var stop = DateTime.UtcNow; Assert.Less(stop - start, TimeSpan.FromSeconds(10)); // we complete each task after one message being processed, so the total number of messages // processed should equal the number of threads, but it's possible that we may process a few more per thread. Assert.IsTrue(messageCt >= numThreads); Assert.IsTrue(messageCt <= messageSendCt, messageCt.ToString()); } }
public async Task SendAndReceiveMessageSafeBatch() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; //@@ string connectionString = "<connection_string>"; //@@ string queueName = "<queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" await using var client = new ServiceBusClient(connectionString); // create the sender ServiceBusSender sender = client.CreateSender(queueName); #region Snippet:ServiceBusSendAndReceiveSafeBatch // add the messages that we plan to send to a local queue Queue <ServiceBusMessage> messages = new Queue <ServiceBusMessage>(); messages.Enqueue(new ServiceBusMessage("First message")); messages.Enqueue(new ServiceBusMessage("Second message")); messages.Enqueue(new ServiceBusMessage("Third message")); // create a message batch that we can send // total number of messages to be sent to the Service Bus queue int messageCount = messages.Count; // while all messages are not sent to the Service Bus queue while (messages.Count > 0) { // start a new batch using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync(); // add the first message to the batch if (messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue once the message is added to the batch messages.Dequeue(); } else { // if the first message can't fit, then it is too large for the batch throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent."); } // add as many messages as possible to the current batch while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek())) { // dequeue the message from the .NET queue as it has been added to the batch messages.Dequeue(); } // now, send the batch await sender.SendMessagesAsync(messageBatch); // if there are any remaining messages in the .NET queue, the while loop repeats } #endregion // create a receiver that we can use to receive the messages ServiceBusReceiver receiver = client.CreateReceiver(queueName); // the received message is a different type as it contains some service set properties IReadOnlyList <ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages : 2); foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages) { // get the message body as a string using an implicit cast string body = receivedMessage.Body.ToString(); } } }
public async Task ManageRules() { await using (var scope = await ServiceBusScope.CreateWithTopic(enablePartitioning: false, enableSession: false)) { #region Snippet:ServiceBusManageRules #if SNIPPET string connectionString = "<connection_string>"; string topicName = "<topic_name>"; string subscriptionName = "<subscription_name>"; #else string connectionString = TestEnvironment.ServiceBusConnectionString; string topicName = scope.TopicName; string subscriptionName = scope.SubscriptionNames.First(); #endif await using var client = new ServiceBusClient(connectionString); await using ServiceBusRuleManager ruleManager = client.CreateRuleManager(topicName, subscriptionName); // By default, subscriptions are created with a default rule that always evaluates to True. In order to filter, we need // to delete the default rule. You can skip this step if you create the subscription with the ServiceBusAdministrationClient, // and specify a the FalseRuleFilter in the create rule options. await ruleManager.DeleteRuleAsync(RuleProperties.DefaultRuleName); await ruleManager.CreateRuleAsync("brand-filter", new CorrelationRuleFilter { Subject = "Toyota" }); // create the sender ServiceBusSender sender = client.CreateSender(topicName); ServiceBusMessage[] messages = { new ServiceBusMessage { Subject = "Ford", ApplicationProperties ={ { "Price", 25000 } } }, new ServiceBusMessage { Subject = "Toyota", ApplicationProperties ={ { "Price", 28000 } } }, new ServiceBusMessage { Subject = "Honda", ApplicationProperties ={ { "Price", 35000 } } } }; // send the messages await sender.SendMessagesAsync(messages); // create a receiver for our subscription that we can use to receive and settle the message ServiceBusReceiver receiver = client.CreateReceiver(topicName, subscriptionName); // receive the message - we only get back the Toyota message while (true) { ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(5)); if (receivedMessage == null) { break; } Console.WriteLine($"Brand: {receivedMessage.Subject}, Price: {receivedMessage.ApplicationProperties["Price"]}"); await receiver.CompleteMessageAsync(receivedMessage); } await ruleManager.CreateRuleAsync("price-filter", new SqlRuleFilter("Price < 30000")); await ruleManager.DeleteRuleAsync("brand-filter"); // we can also use the rule manager to iterate over the rules on the subscription. await foreach (RuleProperties rule in ruleManager.GetRulesAsync()) { // we should only have 1 rule at this point - "price-filter" Console.WriteLine(rule.Name); } // send the messages again - because the subscription rules are evaluated when the messages are first enqueued, adding rules // for messages that are already in a subscription would have no effect. await sender.SendMessagesAsync(messages); // receive the messages - we get back both the Ford and the Toyota while (true) { ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(5)); if (receivedMessage == null) { break; } Console.WriteLine($"Brand: {receivedMessage.Subject}, Price: {receivedMessage.ApplicationProperties["Price"]}"); } #endregion } }
public async Task DeadLetterMessages(bool useSpecificSession) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); var messageCount = 10; var sessionId = "sessionId1"; using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var receiver = await client.AcceptSessionAsync( scope.QueueName, useSpecificSession?sessionId : null); var remainingMessages = messageCount; var messageEnum = messages.GetEnumerator(); while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); await receiver.DeadLetterMessageAsync(item.LockToken, "testReason", "testDescription"); } } Assert.AreEqual(0, remainingMessages); var peekedMessage = receiver.PeekMessageAsync(); Assert.IsNull(peekedMessage.Result); messageEnum.Reset(); remainingMessages = messageCount; var deadLetterReceiver = client.CreateReceiver(scope.QueueName, new ServiceBusReceiverOptions { SubQueue = SubQueue.DeadLetter }); while (remainingMessages > 0) { foreach (var msg in await deadLetterReceiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, msg.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, msg.SessionId); Assert.AreEqual("testReason", msg.DeadLetterReason); Assert.AreEqual("testDescription", msg.DeadLetterErrorDescription); await deadLetterReceiver.CompleteMessageAsync(msg.LockToken); } } Assert.AreEqual(0, remainingMessages); var deadLetterMessage = await deadLetterReceiver.PeekMessageAsync(); Assert.IsNull(deadLetterMessage); } }
public async Task ProcessMessages() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; await using var client = CreateClient(); #region Snippet:ServiceBusProcessMessages //@@ string connectionString = "<connection_string>"; //@@ string queueName = "<queue_name>"; // since ServiceBusClient implements IAsyncDisposable we create it with "await using" //@@ await using var client = new ServiceBusClient(connectionString); // create the sender ServiceBusSender sender = client.CreateSender(queueName); // create a set of messages that we can send ServiceBusMessage[] messages = new ServiceBusMessage[] { new ServiceBusMessage("First"), new ServiceBusMessage("Second") }; // send the message batch await sender.SendMessagesAsync(messages); #region Snippet:ServiceBusConfigureProcessor // create the options to use for configuring the processor var options = new ServiceBusProcessorOptions { // By default or when AutoCompleteMessages is set to true, the processor will complete the message after executing the message handler // Set AutoCompleteMessages to false to [settle messages](https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock) on your own. // In both cases, if the message handler throws an exception without settling the message, the processor will abandon the message. AutoCompleteMessages = false, // I can also allow for multi-threading MaxConcurrentCalls = 2 }; // create a processor that we can use to process the messages await using ServiceBusProcessor processor = client.CreateProcessor(queueName, options); // configure the message and error handler to use processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler; async Task MessageHandler(ProcessMessageEventArgs args) { string body = args.Message.Body.ToString(); Console.WriteLine(body); // we can evaluate application logic and use that to determine how to settle the message. await args.CompleteMessageAsync(args.Message); } Task ErrorHandler(ProcessErrorEventArgs args) { // the error source tells me at what point in the processing an error occurred Console.WriteLine(args.ErrorSource); // the fully qualified namespace is available Console.WriteLine(args.FullyQualifiedNamespace); // as well as the entity path Console.WriteLine(args.EntityPath); Console.WriteLine(args.Exception.ToString()); return(Task.CompletedTask); } // start processing await processor.StartProcessingAsync(); // since the processing happens in the background, we add a Conole.ReadKey to allow the processing to continue until a key is pressed. Console.ReadKey(); #endregion #endregion } }
public async Task DeadLetterMessagesSubscription(bool useSpecificSession) { await using (var scope = await ServiceBusScope.CreateWithTopic(enablePartitioning: false, enableSession: true)) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.TopicName); var messageCount = 10; var sessionId = "sessionId1"; using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); IEnumerable <ServiceBusMessage> messages = AddMessages(batch, messageCount, sessionId).AsEnumerable <ServiceBusMessage>(); await sender.SendMessagesAsync(batch); var topicName = scope.TopicName; var subscriptionName = scope.SubscriptionNames.First(); var receiver = await client.AcceptSessionAsync( topicName : topicName, subscriptionName : subscriptionName, useSpecificSession?sessionId : null); var remainingMessages = messageCount; var messageEnum = messages.GetEnumerator(); while (remainingMessages > 0) { foreach (var item in await receiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, item.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); var props = new Dictionary <string, object>(); // these should be ignored by DeadLetter property getters as they are not strings props[AmqpMessageConstants.DeadLetterReasonHeader] = DateTime.UtcNow; props[AmqpMessageConstants.DeadLetterErrorDescriptionHeader] = DateTime.UtcNow; await receiver.DeadLetterMessageAsync(item.LockToken, props); } } Assert.AreEqual(0, remainingMessages); var peekedMessage = receiver.PeekMessageAsync(); Assert.IsNull(peekedMessage.Result); messageEnum.Reset(); remainingMessages = messageCount; var deadLetterReceiver = client.CreateReceiver(topicName, subscriptionName, new ServiceBusReceiverOptions { SubQueue = SubQueue.DeadLetter }); while (remainingMessages > 0) { foreach (var msg in await deadLetterReceiver.ReceiveMessagesAsync(remainingMessages)) { remainingMessages--; messageEnum.MoveNext(); Assert.AreEqual(messageEnum.Current.MessageId, msg.MessageId); Assert.AreEqual(messageEnum.Current.SessionId, msg.SessionId); Assert.IsNull(msg.DeadLetterErrorDescription); Assert.IsNull(msg.DeadLetterReason); Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterReasonHeader]); Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterErrorDescriptionHeader]); await deadLetterReceiver.CompleteMessageAsync(msg.LockToken); } } Assert.AreEqual(0, remainingMessages); var deadLetterMessage = await deadLetterReceiver.PeekMessageAsync(); Assert.IsNull(deadLetterMessage); } }
public async Task ReceiverCanReconnectToSameSession(bool isSessionSpecified) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true, lockDuration: TimeSpan.FromSeconds(5))) { await using var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); await sender.SendMessagesAsync(GetMessages(3, "sessionId1")); // send another session message before the one we are interested in to make sure that when isSessionSpecified=true, it is being respected await sender.SendMessagesAsync(GetMessages(3, "sessionId2")); ServiceBusSessionReceiver receiver = await client.AcceptSessionAsync( scope.QueueName, isSessionSpecified? "sessionId1" : null); if (isSessionSpecified) { Assert.AreEqual("sessionId1", receiver.SessionId); } var firstMessage = await receiver.ReceiveMessageAsync(); Assert.AreEqual(receiver.SessionId, firstMessage.SessionId); var sessionId = receiver.SessionId; await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5)); var secondMessage = await receiver.ReceiveMessageAsync(); Assert.AreEqual(sessionId, receiver.SessionId); Assert.AreEqual(receiver.SessionId, secondMessage.SessionId); // Even though the receiver has re-established the session link, since the first message was // received before we reconnected, the message won't be able to be settled. This is analogous // to the case of reconnecting a regular non-session link and getting a MessageLockLost error. Assert.That( async() => await receiver.CompleteMessageAsync(firstMessage), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)).EqualTo(ServiceBusFailureReason.SessionLockLost)); await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5)); // If another receiver accepts the session after the lock is lost, we expect a SessionCannotBeLocked error, // when we try to receive again with our initial receiver. ServiceBusSessionReceiver secondReceiver = await client.AcceptSessionAsync( scope.QueueName, sessionId); try { await receiver.ReceiveMessageAsync(); } catch (ServiceBusException ex) when(ex.Reason == ServiceBusFailureReason.SessionCannotBeLocked) { return; } catch (Exception ex) { Assert.Fail($"Expected exception not thrown: {ex}"); } Assert.Fail("No exception thrown!"); } }
public async Task AutoLockRenewalWorks(int numThreads) { var lockDuration = TimeSpan.FromSeconds(10); await using (var scope = await ServiceBusScope.CreateWithQueue( enablePartitioning: false, enableSession: false, lockDuration: lockDuration)) { await using var client = GetClient(); ServiceBusSender sender = client.CreateSender(scope.QueueName); using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync(); var messageSendCt = numThreads; ServiceBusMessageBatch messageBatch = AddMessages(batch, messageSendCt); await sender.SendMessagesAsync(messageBatch); var options = new ServiceBusProcessorOptions { MaxConcurrentCalls = numThreads, AutoComplete = false }; var processor = client.CreateProcessor(scope.QueueName, options); int messageCt = 0; TaskCompletionSource <bool>[] completionSources = Enumerable .Range(0, numThreads) .Select(index => new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously)) .ToArray(); var completionSourceIndex = -1; processor.ProcessMessageAsync += ProcessMessage; processor.ProcessErrorAsync += ExceptionHandler; await processor.StartProcessingAsync(); async Task ProcessMessage(ProcessMessageEventArgs args) { try { var message = args.Message; var lockedUntil = message.LockedUntil; await Task.Delay(lockDuration); Assert.That(message.LockedUntil > lockedUntil, $"{lockedUntil},{DateTime.UtcNow}"); await args.CompleteAsync(message, args.CancellationToken); Interlocked.Increment(ref messageCt); } finally { var setIndex = Interlocked.Increment(ref completionSourceIndex); if (setIndex < numThreads) { completionSources[setIndex].SetResult(true); } } } await Task.WhenAll(completionSources.Select(source => source.Task)); Assert.IsTrue(processor.IsProcessing); await processor.StopProcessingAsync(); Assert.IsFalse(processor.IsProcessing); Assert.AreEqual(numThreads, messageCt); } }
public async Task SessionProcessorActivities() { ClientDiagnosticListener.ProducedLink[] messageActivities = null; int messageProcessedCt = 0; bool callbackExecuted = false; _listener = new ClientDiagnosticListener( EntityScopeFactory.DiagnosticNamespace, scopeStartCallback: scope => { if (scope.Name == DiagnosticProperty.ProcessSessionMessageActivityName) { Assert.IsNotNull(messageActivities); Assert.AreEqual( messageActivities[messageProcessedCt], scope.Links.Single()); callbackExecuted = true; } }); await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); ServiceBusSender sender = client.CreateSender(scope.QueueName); var messageCt = 2; var msgs = ServiceBusTestUtilities.GetMessages(messageCt, "sessionId"); await sender.SendMessagesAsync(msgs); Activity[] sendActivities = AssertSendActivities(false, sender, msgs); messageActivities = sendActivities.Select(a => new ClientDiagnosticListener.ProducedLink(a.ParentId, a.TraceStateString)).ToArray(); ServiceBusSessionProcessor processor = client.CreateSessionProcessor(scope.QueueName, new ServiceBusSessionProcessorOptions { AutoCompleteMessages = false, SessionIdleTimeout = TimeSpan.FromSeconds(10), MaxConcurrentSessions = 1 }); TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(); processor.ProcessMessageAsync += args => { if (++messageProcessedCt == messageCt) { tcs.SetResult(true); } return(Task.CompletedTask); }; processor.ProcessErrorAsync += ServiceBusTestUtilities.ExceptionHandler; await processor.StartProcessingAsync(); await tcs.Task; await processor.StopProcessingAsync(); for (int i = 0; i < messageCt; i++) { _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveActivityName); var processScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ProcessSessionMessageActivityName); AssertCommonTags(processScope.Activity, processor.EntityPath, processor.FullyQualifiedNamespace); } Assert.IsTrue(callbackExecuted); } }