예제 #1
0
        public void GetSessionStateExceptionLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();
            var mockConnection        = GetMockConnection(mockTransportReceiver);

            mockTransportReceiver.Setup(
                transportReceiver => transportReceiver.GetStateAsync(
                    It.IsAny <CancellationToken>()))
            .Throws(new Exception());
            var receiver = new ServiceBusSessionReceiver(mockConnection.Object, "queueName", new ServiceBusReceiverOptions())
            {
                Logger = mockLogger.Object
            };

            Assert.That(
                async() => await receiver.GetSessionStateAsync(),
                Throws.InstanceOf <Exception>());

            mockLogger
            .Verify(
                log => log.GetSessionStateStart(
                    receiver.Identifier,
                    It.IsAny <string>()),
                Times.Once);
            mockLogger
            .Verify(
                log => log.GetSessionStateException(
                    receiver.Identifier,
                    It.IsAny <string>()),
                Times.Once);
        }
예제 #2
0
        public async Task GetSessionStateLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();
            var mockConnection        = GetMockConnection(mockTransportReceiver);
            var receiver = new ServiceBusSessionReceiver(
                mockConnection.Object,
                "queueName",
                new ServiceBusPlugin[] { },
                new ServiceBusSessionReceiverOptions(),
                cancellationToken: CancellationToken.None)
            {
                Logger = mockLogger.Object
            };

            await receiver.GetSessionStateAsync();

            mockLogger
            .Verify(
                log => log.GetSessionStateStart(
                    receiver.Identifier,
                    It.IsAny <string>()),
                Times.Once);
            mockLogger
            .Verify(
                log => log.GetSessionStateComplete(
                    receiver.Identifier),
                Times.Once);
        }
        public async Task RenewSessionLockLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();

            mockTransportReceiver.Setup(r => r.SessionId).Returns("sessionId");
            var mockConnection = GetMockConnection(mockTransportReceiver);
            var receiver       = new ServiceBusSessionReceiver(mockConnection.Object, "queueName", new ServiceBusSessionReceiverOptions(), cancellationToken: CancellationToken.None)
            {
                Logger = mockLogger.Object
            };

            await receiver.RenewSessionLockAsync();

            mockLogger
            .Verify(
                log => log.RenewSessionLockStart(
                    receiver.Identifier,
                    "sessionId"),
                Times.Once);
            mockLogger
            .Verify(
                log => log.RenewSessionLockComplete(
                    receiver.Identifier,
                    "sessionId"),
                Times.Once);
        }
        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());
            };
        }
예제 #5
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));
            }
        }
예제 #6
0
 public MockedServiceBusClient(
     string queue,
     string replyQueue,
     ServiceBusSender serviceBusSender,
     ServiceBusSessionReceiver serviceBusSessionReceiver)
 {
     _queue                     = queue;
     _replyQueue                = replyQueue;
     _serviceBusSender          = serviceBusSender;
     _serviceBusSessionReceiver = serviceBusSessionReceiver;
 }
예제 #7
0
        public void SessionReceiverCannotPerformMessageLock()
        {
            var receiver = new ServiceBusSessionReceiver(
                GetMockedConnection(),
                "fakeQueue",
                options: new ServiceBusReceiverOptions());

            Assert.That(async() => await receiver.RenewMessageLockAsync(
                            new ServiceBusReceivedMessage()),
                        Throws.InstanceOf <InvalidOperationException>());
        }
예제 #8
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);
        }
        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());
            }
        }
예제 #10
0
        public async Task RenewSessionLock(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 messageCount          = 1;
                var sessionId1            = "sessionId1";
                ServiceBusMessage message = GetMessage(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.SendMessageAsync(GetMessage("sessionId2"));

                await sender.SendMessageAsync(message);

                ServiceBusSessionReceiver receiver = await client.CreateSessionReceiverAsync(
                    scope.QueueName,
                    new ServiceBusSessionReceiverOptions
                {
                    SessionId = isSessionSpecified ? sessionId1 : null
                });

                if (isSessionSpecified)
                {
                    Assert.AreEqual(sessionId1, receiver.SessionId);
                }
                ServiceBusReceivedMessage[] receivedMessages = (await receiver.ReceiveMessagesAsync(messageCount)).ToArray();

                var receivedMessage         = receivedMessages.First();
                var firstLockedUntilUtcTime = receiver.SessionLockedUntil;

                // Sleeping for 10 seconds...
                await Task.Delay(10000);

                await receiver.RenewSessionLockAsync();

                Assert.True(receiver.SessionLockedUntil >= firstLockedUntilUtcTime + TimeSpan.FromSeconds(10));

                // Complete Messages
                await receiver.CompleteMessageAsync(receivedMessage.LockToken);

                Assert.AreEqual(messageCount, receivedMessages.Length);
                if (isSessionSpecified)
                {
                    Assert.AreEqual(message.MessageId, receivedMessage.MessageId);
                }

                var peekedMessage = receiver.PeekMessageAsync();
                Assert.IsNull(peekedMessage.Result);
            }
        }
예제 #11
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);
            }
        }
예제 #12
0
        public async Task SetSessionStateLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();
            var mockConnection        = GetMockConnection(mockTransportReceiver);
            var receiver = new ServiceBusSessionReceiver(
                mockConnection.Object,
                "queueName",
                new ServiceBusPlugin[] { },
                new ServiceBusSessionReceiverOptions())
            {
                Logger = mockLogger.Object
            };

            await receiver.SetSessionStateAsync(default);
        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.CreateBatchAsync();

                messageBatch.TryAdd(
                    new ServiceBusMessage(Encoding.UTF8.GetBytes("First"))
                {
                    SessionId = "Session1"
                });
                messageBatch.TryAdd(
                    new ServiceBusMessage(Encoding.UTF8.GetBytes("Second"))
                {
                    SessionId = "Session2"
                });

                // send the message batch
                await sender.SendAsync(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.ReceiveAsync();

                Console.WriteLine(receivedMessage.SessionId);

                #endregion
                Assert.AreEqual(Encoding.UTF8.GetBytes("Second"), receivedMessage.Body.AsBytes().ToArray());
                Assert.AreEqual("Session2", receivedMessage.SessionId);
            }
        }
예제 #14
0
        public async Task SetSessionStateLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();

            mockTransportReceiver.Setup(r => r.SessionId).Returns("sessionId");
            var mockConnection = GetMockConnection(mockTransportReceiver);
            var receiver       = new ServiceBusSessionReceiver(
                mockConnection.Object,
                "queueName",
                new ServiceBusSessionReceiverOptions(),
                cancellationToken: CancellationToken.None)
            {
                Logger = mockLogger.Object
            };

            await receiver.SetSessionStateAsync(default);
예제 #15
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());
        }
예제 #16
0
        /// <summary>
        /// This method completes processing of the specified message, after the job function has been invoked.
        /// </summary>
        /// <remarks>
        /// The message is completed by the ServiceBus SDK based on how the <see cref="ServiceBusSessionProcessorOptions.AutoCompleteMessages"/> option
        /// is configured. E.g. if <see cref="ServiceBusSessionProcessorOptions.AutoCompleteMessages"/> is false, it is up to the job function to complete
        /// the message.
        /// </remarks>
        /// <param name="receiver"></param>
        /// <param name="message"></param>
        /// <param name="result">The <see cref="FunctionResult"/> from the job invocation.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use</param>
        /// <returns>A <see cref="Task"/> that will complete the message processing.</returns>
        public virtual Task CompleteProcessingMessageAsync(ServiceBusSessionReceiver receiver, ServiceBusReceivedMessage message, FunctionResult result, CancellationToken cancellationToken)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            cancellationToken.ThrowIfCancellationRequested();

            if (!result.Succeeded)
            {
                // if the invocation failed, we must propagate the
                // exception back to SB so it can handle message state
                // correctly
                throw result.Exception;
            }

            return(Task.CompletedTask);
        }
        internal async Task ProcessSessionMessageAsync(ProcessSessionMessageEventArgs args)
        {
            using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(args.CancellationToken, _cancellationTokenSource.Token))
            {
                ServiceBusSessionReceiver receiver = (ServiceBusSessionReceiver)typeof(ProcessSessionMessageEventArgs).GetField("_sessionReceiver", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(args);

                if (!await _sessionMessageProcessor.BeginProcessingMessageAsync(receiver, args.Message, linkedCts.Token).ConfigureAwait(false))
                {
                    return;
                }

                ServiceBusTriggerInput input = ServiceBusTriggerInput.CreateSingle(args.Message);
                input.SessionReceiver = receiver;

                TriggeredFunctionData data   = input.GetTriggerFunctionData();
                FunctionResult        result = await _triggerExecutor.TryExecuteAsync(data, linkedCts.Token).ConfigureAwait(false);

                await _sessionMessageProcessor.CompleteProcessingMessageAsync(receiver, args.Message, result, linkedCts.Token).ConfigureAwait(false);
            }
        }
예제 #18
0
        public async Task RoundRobinSessions()
        {
            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 messageCt             = 10;
                HashSet <string> sessions = new HashSet <string>()
                {
                    "1", "2", "3"
                };
                // send the messages
                foreach (string session in sessions)
                {
                    using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync();

                    ServiceBusMessageBatch messageBatch = AddMessages(batch, messageCt, session);
                    await sender.SendMessagesAsync(messageBatch);
                }

                // create receiver not scoped to a specific session
                for (int i = 0; i < 10; i++)
                {
                    ServiceBusSessionReceiver receiver = await client.AcceptNextSessionAsync(scope.QueueName);

                    foreach (ServiceBusReceivedMessage peekedMessage in await receiver.PeekMessagesAsync(
                                 fromSequenceNumber: 1,
                                 maxMessages: 10))
                    {
                        var sessionId = receiver.SessionId;
                        Assert.AreEqual(sessionId, peekedMessage.SessionId);
                    }

                    // Close the receiver client when we are done with it. Since the sessionClient doesn't own the underlying connection, the connection remains open, but the session link will be closed.
                    await receiver.DisposeAsync();
                }
            }
        }
예제 #19
0
        public async Task RenewSessionLockLogsEvents()
        {
            var mockLogger            = new Mock <ServiceBusEventSource>();
            var mockTransportReceiver = new Mock <TransportReceiver>();
            var mockConnection        = GetMockConnection(mockTransportReceiver);
            var receiver = new ServiceBusSessionReceiver(mockConnection.Object, "queueName", new ServiceBusReceiverOptions())
            {
                Logger = mockLogger.Object
            };

            await receiver.RenewSessionLockAsync();

            mockLogger
            .Verify(
                log => log.RenewSessionLockStart(
                    receiver.Identifier,
                    It.IsAny <string>()),
                Times.Once);
            mockLogger
            .Verify(
                log => log.RenewSessionLockComplete(
                    receiver.Identifier),
                Times.Once);
        }
예제 #20
0
 /// <summary>
 /// This method is called when there is a new message to process, before the job function is invoked.
 /// This allows any preprocessing to take place on the message before processing begins.
 /// </summary>
 /// <param name="receiver"></param>
 /// <param name="message"></param>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
 /// <returns>A <see cref="Task"/> that returns true if the message processing should continue, false otherwise.</returns>
 public virtual Task <bool> BeginProcessingMessageAsync(ServiceBusSessionReceiver receiver, ServiceBusReceivedMessage message, CancellationToken cancellationToken)
 {
     return(Task.FromResult <bool>(true));
 }
예제 #21
0
 internal ServiceBusSessionMessageActions(ServiceBusSessionReceiver receiver) : base(receiver)
 {
     _receiver = receiver;
 }
        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);
                }
            }
        }
예제 #23
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!");
            }
        }
예제 #24
0
 private AzureSessionReceiverServiceBus(ServiceBusSessionReceiver serviceBusSessionReceiver)
 {
     _serviceBusSessionReceiver = serviceBusSessionReceiver;
 }
예제 #25
0
 internal static AzureSessionReceiverServiceBus Wrap(ServiceBusSessionReceiver sessionReceiver)
 {
     return(new(sessionReceiver));
 }
예제 #26
0
 internal PluginSessionReceiver(ServiceBusSessionReceiver receiver, IEnumerable <Func <ServiceBusReceivedMessage, Task> > plugins)
 {
     _plugins  = plugins;
     _receiver = receiver;
 }
예제 #27
0
        async Task <long> PurgeSessionEntity()
        {
            long totalMessagesPurged                  = 0;
            var  consecutiveSessionTimeOuts           = 0;
            ServiceBusSessionReceiver sessionReceiver = null;
            long messagesToPurgeCount                 = await GetMessageCount(deadLetterQueueData : false)
                                                        .ConfigureAwait(false);

            var client = new ServiceBusClient(
                serviceBusHelper.ConnectionString,
                new ServiceBusClientOptions
            {
                TransportType = serviceBusHelper.TransportType
            });

            try
            {
                const int enoughZeroReceives = 3;

                while (consecutiveSessionTimeOuts < enoughZeroReceives && totalMessagesPurged < messagesToPurgeCount)
                {
                    sessionReceiver = await CreateServiceBusSessionReceiver(
                        client,
                        purgeDeadLetterQueueInstead : false)
                                      .ConfigureAwait(false);

                    var consecutiveZeroBatchReceives = 0;

                    while (consecutiveZeroBatchReceives < enoughZeroReceives &&
                           totalMessagesPurged < messagesToPurgeCount)
                    {
                        var messages = await sessionReceiver.ReceiveMessagesAsync(
                            maxMessages : 1000,
                            maxWaitTime : TimeSpan.FromMilliseconds(1000))
                                       .ConfigureAwait(false);

                        if (messages != null && messages.Any())
                        {
                            Interlocked.Add(ref totalMessagesPurged, messages.Count());
                            consecutiveZeroBatchReceives = 0;
                        }
                        else
                        {
                            ++consecutiveZeroBatchReceives;
                        }
                    }

                    await sessionReceiver.CloseAsync().ConfigureAwait(false);
                }
            }
            catch (TimeoutException)
            {
                ++consecutiveSessionTimeOuts;
            }
            finally
            {
                await client.DisposeAsync().ConfigureAwait(false);
            }

            return(totalMessagesPurged);
        }