Пример #1
0
        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());
            };
        }
Пример #3
0
        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());
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
            }
        }
Пример #8
0
        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);
                }
            }
        }
Пример #10
0
        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!");
            }
        }
Пример #11
0
 public Task <ServiceBusReceivedMessage?> ReceiveMessageAsync <T>(TimeSpan timeout)
 {
     return(_serviceBusSessionReceiver.ReceiveMessageAsync(timeout));
 }