public async Task ReceiverThrowsAfterSessionLockLost(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(ServiceBusTestUtilities.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(ServiceBusTestUtilities.GetMessages(3, "sessionId2")); ServiceBusSessionReceiver receiver = await client.AcceptSessionAsync( scope.QueueName, isSessionSpecified? "sessionId1" : null); if (isSessionSpecified) { Assert.AreEqual("sessionId1", receiver.SessionId); } var message = await receiver.ReceiveMessageAsync(); Assert.AreEqual(receiver.SessionId, message.SessionId); var sessionId = receiver.SessionId; await Task.Delay((receiver.SessionLockedUntil - DateTime.UtcNow) + TimeSpan.FromSeconds(5)); Assert.IsTrue(receiver.IsClosed); Assert.That(async() => await receiver.ReceiveMessageAsync(), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.SetSessionStateAsync(null), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.GetSessionStateAsync(), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.CompleteMessageAsync(message), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.CompleteMessageAsync(message), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.DeadLetterMessageAsync(message), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); Assert.That(async() => await receiver.DeferMessageAsync(message), Throws.InstanceOf <ServiceBusException>().And.Property(nameof(ServiceBusException.Reason)) .EqualTo(ServiceBusFailureReason.SessionLockLost)); } }
public async Task TransactionalSetSessionState() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { await using var client = CreateClient(); string queueName = scope.QueueName; #region Snippet:ServiceBusTransactionalSetSessionState //@@ 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); ServiceBusSender sender = client.CreateSender(queueName); await sender.SendMessageAsync(new ServiceBusMessage("my message") { SessionId = "sessionId" }); ServiceBusSessionReceiver receiver = await client.AcceptNextSessionAsync(queueName); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(); var state = Encoding.UTF8.GetBytes("some state"); using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await receiver.CompleteMessageAsync(receivedMessage); await receiver.SetSessionStateAsync(new BinaryData(state)); ts.Complete(); } #endregion var bytes = await receiver.GetSessionStateAsync(); Assert.AreEqual(state, bytes.ToArray()); }; }
public override async Task <ServiceBusReceivedMessage> ReceiveMessageAsync(TimeSpan?maxWaitTime = null, CancellationToken cancellationToken = default) { ServiceBusReceivedMessage message = await _receiver.ReceiveMessageAsync(maxWaitTime, cancellationToken).ConfigureAwait(false); foreach (var plugin in _plugins) { await plugin.Invoke(message); } return(message); }
public async Task SendAndReceiveSessionMessage() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { #region Snippet:ServiceBusSendAndReceiveSessionMessage #if SNIPPET string connectionString = "<connection_string>"; string queueName = "<queue_name>"; #else string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; #endif // 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 session message that we can send ServiceBusMessage message = new ServiceBusMessage(Encoding.UTF8.GetBytes("Hello world!")) { SessionId = "mySessionId" }; // send the message await sender.SendMessageAsync(message); // create a session receiver that we can use to receive the message. Since we don't specify a // particular session, we will get the next available session from the service. #region Snippet:ServiceBusReceiveNextSession ServiceBusSessionReceiver receiver = await client.AcceptNextSessionAsync(queueName); // the received message is a different type as it contains some service set properties ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(); Console.WriteLine(receivedMessage.SessionId); #endregion // we can also set arbitrary session state using this receiver // the state is specific to the session, and not any particular message await receiver.SetSessionStateAsync(new BinaryData("some state")); // the state can be retrieved for the session as well BinaryData state = await receiver.GetSessionStateAsync(); #endregion Assert.AreEqual(Encoding.UTF8.GetBytes("Hello world!"), receivedMessage.Body.ToArray()); Assert.AreEqual("mySessionId", receivedMessage.SessionId); Assert.AreEqual(Encoding.UTF8.GetBytes("some state"), state.ToArray()); } }
public async Task CrossEntityTransactionSessionProcessorRollback() { await using var client = CreateCrossEntityTxnClient(); await using var queueA = await ServiceBusScope.CreateWithQueue(enablePartitioning : false, enableSession : true); await using var queueB = await ServiceBusScope.CreateWithQueue(enablePartitioning : false, enableSession : true); await using var queueC = await ServiceBusScope.CreateWithQueue(enablePartitioning : false, enableSession : true); var senderA = client.CreateSender(queueA.QueueName); await using var processorA = client.CreateSessionProcessor(queueA.QueueName); var senderB = client.CreateSender(queueB.QueueName); var senderC = client.CreateSender(queueC.QueueName); var message = new ServiceBusMessage { SessionId = "sessionId" }; await senderA.SendMessageAsync(message); processorA.ProcessErrorAsync += ExceptionHandler; var tcs = new TaskCompletionSource <bool>(); processorA.ProcessMessageAsync += async args => { using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await args.CompleteMessageAsync(args.Message); await senderB.SendMessageAsync(message); await senderC.SendMessageAsync(message); } tcs.TrySetResult(true); }; await processorA.StartProcessingAsync(); await tcs.Task; await processorA.StopProcessingAsync(); // transaction wasn't committed - verify that it was rolled back ServiceBusSessionReceiver receiverA = await client.AcceptNextSessionAsync(queueA.QueueName); ServiceBusReceivedMessage receivedMessage = await receiverA.ReceiveMessageAsync(); Assert.IsNotNull(receivedMessage); }
public async Task GetAndSetSessionStateTest(bool isSessionSpecified) { 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 sessionId = "test-sessionId"; ServiceBusMessage message = GetMessage(sessionId); await sender.SendMessageAsync(message); ServiceBusSessionReceiver receiver = await client.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = isSessionSpecified ? sessionId : null }); ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(); Assert.AreEqual(message.MessageId, receivedMessage.MessageId); Assert.AreEqual(message.SessionId, receivedMessage.SessionId); Assert.AreEqual(message.Body.ToBytes().ToArray(), receivedMessage.Body.ToBytes().ToArray()); var sessionStateString = "Received Message From Session!"; var sessionState = Encoding.UTF8.GetBytes(sessionStateString); await receiver.SetSessionStateAsync(sessionState); var returnedSessionState = await receiver.GetSessionStateAsync(); var returnedSessionStateString = Encoding.UTF8.GetString(returnedSessionState); Assert.AreEqual(sessionStateString, returnedSessionStateString); // Complete message using Session Receiver await receiver.CompleteMessageAsync(receivedMessage); var peekedMessage = receiver.PeekMessageAsync(); Assert.IsNull(peekedMessage.Result); sessionStateString = "Completed Message On Session!"; sessionState = Encoding.UTF8.GetBytes(sessionStateString); await receiver.SetSessionStateAsync(sessionState); returnedSessionState = await receiver.GetSessionStateAsync(); returnedSessionStateString = Encoding.UTF8.GetString(returnedSessionState); Assert.AreEqual(sessionStateString, returnedSessionStateString); } }
public async Task ReceiveFromSpecificSession() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true)) { string connectionString = TestEnvironment.ServiceBusConnectionString; string queueName = scope.QueueName; // 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")) { SessionId = "Session1" }); messageBatch.TryAddMessage( new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")) { SessionId = "Session2" }); // send the message batch await sender.SendMessagesAsync(messageBatch); #region Snippet:ServiceBusReceiveFromSpecificSession // create a receiver specifying a particular session ServiceBusSessionReceiver receiver = await client.CreateSessionReceiverAsync( queueName, new ServiceBusSessionReceiverOptions { SessionId = "Session2" }); // the received message is a different type as it contains some service set properties ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync(); Console.WriteLine(receivedMessage.SessionId); #endregion Assert.AreEqual(Encoding.UTF8.GetBytes("Second"), receivedMessage.Body.ToBytes().ToArray()); Assert.AreEqual("Session2", receivedMessage.SessionId); } }
public static async Task <ServiceBusReceivedMessage> GetMessageFromSessionAsync(string connectionString, string queueName, string sessionId) { await using var client = new ServiceBusClient(connectionString); ServiceBusSessionReceiver receiver = null; if (string.IsNullOrEmpty(sessionId)) { receiver = await client.AcceptNextSessionAsync(queueName); } else { receiver = await client.AcceptSessionAsync(queueName, sessionId); } // the received message is a different type as it contains some service set properties return(await receiver.ReceiveMessageAsync()); }
public async Task CreateFromReceivedMessageCopiesProperties() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: true, enableSession: true)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var sender = client.CreateSender(scope.QueueName); var msg = new ServiceBusMessage(new BinaryData(GetRandomBuffer(100))); msg.ContentType = "contenttype"; msg.CorrelationId = "correlationid"; msg.Subject = "label"; msg.MessageId = "messageId"; msg.PartitionKey = "key"; msg.ApplicationProperties.Add("testProp", "my prop"); msg.ReplyTo = "replyto"; msg.ReplyToSessionId = "replytosession"; msg.ScheduledEnqueueTime = DateTimeOffset.Now; msg.SessionId = "key"; msg.TimeToLive = TimeSpan.FromSeconds(60); msg.To = "to"; await sender.SendMessageAsync(msg); ServiceBusSessionReceiver receiver = await client.AcceptNextSessionAsync(scope.QueueName); ServiceBusReceivedMessage received = await receiver.ReceiveMessageAsync(); AmqpAnnotatedMessage rawReceived = received.GetRawAmqpMessage(); Assert.IsNotNull(rawReceived.Header.DeliveryCount); Assert.IsTrue(rawReceived.MessageAnnotations.ContainsKey(AmqpMessageConstants.LockedUntilName)); Assert.IsTrue(rawReceived.MessageAnnotations.ContainsKey(AmqpMessageConstants.SequenceNumberName)); Assert.IsTrue(rawReceived.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueueSequenceNumberName)); Assert.IsTrue(rawReceived.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueuedTimeUtcName)); AssertMessagesEqual(msg, received); var toSend = new ServiceBusMessage(received); AmqpAnnotatedMessage rawSend = toSend.GetRawAmqpMessage(); // verify that all system set properties have been cleared out Assert.IsNull(rawSend.Header.DeliveryCount); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.LockedUntilName)); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.SequenceNumberName)); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.DeadLetterSourceName)); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueueSequenceNumberName)); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueuedTimeUtcName)); Assert.IsFalse(rawSend.MessageAnnotations.ContainsKey(AmqpMessageConstants.DeadLetterSourceName)); Assert.IsFalse(toSend.ApplicationProperties.ContainsKey(AmqpMessageConstants.DeadLetterReasonHeader)); Assert.IsFalse(toSend.ApplicationProperties.ContainsKey(AmqpMessageConstants.DeadLetterErrorDescriptionHeader)); AssertMessagesEqual(toSend, received); void AssertMessagesEqual(ServiceBusMessage sentMessage, ServiceBusReceivedMessage received) { Assert.IsTrue(received.Body.ToArray().SequenceEqual(sentMessage.Body.ToArray())); Assert.AreEqual(received.ContentType, sentMessage.ContentType); Assert.AreEqual(received.CorrelationId, sentMessage.CorrelationId); Assert.AreEqual(received.Subject, sentMessage.Subject); Assert.AreEqual(received.ContentType, sentMessage.ContentType); Assert.AreEqual(received.CorrelationId, sentMessage.CorrelationId); Assert.AreEqual(received.MessageId, sentMessage.MessageId); Assert.AreEqual(received.PartitionKey, sentMessage.PartitionKey); Assert.AreEqual((string)received.ApplicationProperties["testProp"], (string)sentMessage.ApplicationProperties["testProp"]); Assert.AreEqual(received.ReplyTo, sentMessage.ReplyTo); Assert.AreEqual(received.ReplyToSessionId, sentMessage.ReplyToSessionId); Assert.AreEqual(received.ScheduledEnqueueTime.UtcDateTime.Second, sentMessage.ScheduledEnqueueTime.UtcDateTime.Second); Assert.AreEqual(received.SessionId, sentMessage.SessionId); Assert.AreEqual(received.TimeToLive, sentMessage.TimeToLive); Assert.AreEqual(received.To, sentMessage.To); Assert.AreEqual(received.TransactionPartitionKey, sentMessage.TransactionPartitionKey); } } }
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.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = 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.CreateSessionReceiverAsync( scope.QueueName, new ServiceBusSessionReceiverOptions { SessionId = 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 Task <ServiceBusReceivedMessage?> ReceiveMessageAsync <T>(TimeSpan timeout) { return(_serviceBusSessionReceiver.ReceiveMessageAsync(timeout)); }