Beispiel #1
8
        public void TryAddRespectsTheBatchLock()
        {
            var mockBatch = new MockTransportBatch();
            var batch     = new ServiceBusMessageBatch(mockBatch);
            var message   = new ServiceBusMessage(new byte[] { 0x21 });

            Assert.That(batch.TryAdd(new ServiceBusMessage(new byte[] { 0x21 })), Is.True, "The message should have been accepted before locking.");

            batch.Lock();
            Assert.That(() => batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>())), Throws.InstanceOf <InvalidOperationException>(), "The batch should not accept messages when locked.");

            batch.Unlock();
            Assert.That(batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>())), Is.True, "The message should have been accepted after unlocking.");
        }
Beispiel #2
0
        public async Task TryAddReturnsFalseIfSizeExceed()
        {
            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);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                // Actual limit is 262144 bytes for a single message.
                Assert.That(() => batch.TryAdd(new ServiceBusMessage(new byte[200000])), Is.True, "A message was rejected by the batch; all messages should be accepted.");
                Assert.That(() => batch.TryAdd(new ServiceBusMessage(new byte[200000])), Is.False, "A message was rejected by the batch; message size exceed.");

                await sender.SendAsync(batch);
            }
        }
        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);
            }
        }
Beispiel #4
0
        public async Task CanSendLargeMessageBatch()
        {
            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);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                // Actual limit is 262144 bytes for a single message.
                batch.TryAdd(new ServiceBusMessage(new byte[100000 / 3]));
                batch.TryAdd(new ServiceBusMessage(new byte[100000 / 3]));
                batch.TryAdd(new ServiceBusMessage(new byte[100000 / 3]));

                await sender.SendAsync(batch);
            }
        }
        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);

                // create a message batch that we can send
                #region Snippet:ServiceBusSendAndReceiveSafeBatch
                ServiceBusMessageBatch messageBatch = await sender.CreateBatchAsync();

                messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("First")));
                messageBatch.TryAdd(new ServiceBusMessage(Encoding.UTF8.GetBytes("Second")));

                // send the message batch
                await sender.SendAsync(messageBatch);

                #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
                IList <ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveBatchAsync(maxMessages : 2);

                foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
                {
                    // get the message body as a string
                    string body = Encoding.UTF8.GetString(receivedMessage.Body.ToArray());
                    Console.WriteLine(body);
                }
                var sentMessagesEnum = messageBatch.AsEnumerable <ServiceBusMessage>().GetEnumerator();
                foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
                {
                    sentMessagesEnum.MoveNext();
                    Assert.AreEqual(sentMessagesEnum.Current.Body.ToArray(), receivedMessage.Body.ToArray());
                }
            }
        }
        public async Task SendBatchManagesLockingTheBatch()
        {
            using var cancellationSource = new CancellationTokenSource();
            cancellationSource.CancelAfter(TimeSpan.FromSeconds(15));

            var completionSource   = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            var mockTransportBatch = new Mock <TransportMessageBatch>();
            var batch = new ServiceBusMessageBatch(mockTransportBatch.Object);
            var mockTransportSender = new Mock <TransportSender>();
            var mockConnection      = new Mock <ServiceBusConnection>();

            mockConnection
            .Setup(connection => connection.RetryOptions)
            .Returns(new ServiceBusRetryOptions());

            mockConnection
            .Setup(connection => connection.CreateTransportSender(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <ServiceBusRetryPolicy>(), It.IsAny <string>()))
            .Returns(mockTransportSender.Object);

            mockConnection
            .Setup(connection => connection.ThrowIfClosed());

            mockTransportBatch
            .Setup(transport => transport.TryAdd(It.IsAny <ServiceBusMessage>()))
            .Returns(true);

            mockTransportSender
            .Setup(transport => transport.SendBatchAsync(It.IsAny <ServiceBusMessageBatch>(), It.IsAny <CancellationToken>()))
            .Returns(async() => await Task.WhenAny(completionSource.Task, Task.Delay(Timeout.Infinite, cancellationSource.Token)));

            Assert.That(batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>())), Is.True, "The batch should not be locked before sending.");

            var sender   = new ServiceBusSender("dummy", null, mockConnection.Object);
            var sendTask = sender.SendAsync(batch);

            Assert.That(() => batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>())), Throws.InstanceOf <InvalidOperationException>(), "The batch should be locked while sending.");
            completionSource.TrySetResult(true);

            await sendTask;

            Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled.");
            Assert.That(batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>())), Is.True, "The batch should not be locked after sending.");

            cancellationSource.Cancel();
        }
        protected ServiceBusMessageBatch AddMessages(ServiceBusMessageBatch batch, int count, string sessionId = null, string partitionKey = null)
        {
            for (int i = 0; i < count; i++)
            {
                Assert.That(() => batch.TryAdd(GetMessage(sessionId, partitionKey)), Is.True, "A message was rejected by the batch; all messages should be accepted.");
            }

            return(batch);
        }
Beispiel #8
0
        public void TryAddIsDelegatedToTheTransportClient()
        {
            var mockBatch = new MockTransportBatch();
            var batch     = new ServiceBusMessageBatch(mockBatch);
            var message   = new ServiceBusMessage(new byte[] { 0x21 });

            Assert.That(batch.TryAdd(message), Is.True, "The message should have been accepted.");
            Assert.That(mockBatch.TryAddCalledWith, Is.SameAs(message), "The message should have been passed with delegation.");
        }
Beispiel #9
0
        public async Task CanSendAnEmptyBodyMessageBatch()
        {
            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);
                using ServiceBusMessageBatch batch = await sender.CreateBatchAsync();

                batch.TryAdd(new ServiceBusMessage(Array.Empty <byte>()));

                await sender.SendAsync(batch);
            }
        }
Beispiel #10
0
        public async Task ProcessSessionMessages()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName        = scope.QueueName;
                await using var client = GetClient();

                #region Snippet:ServiceBusProcessSessionMessages
                //@@ 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);

                // get the sender
                ServiceBusSender sender = client.GetSender(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.SendBatchAsync(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.
                    AutoComplete = false,

                    // I can also allow for multi-threading
                    MaxConcurrentCalls = 2
                };

                // get a session processor that we can use to process the messages
                ServiceBusSessionProcessor processor = client.GetSessionProcessor(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(ProcessSessionMessageEventArgs args)
                {
                    string body = Encoding.Default.GetString(args.Message.Body.ToArray());

                    Console.WriteLine(body);

                    // we can evaluate application logic and use that to determine how to settle the message.
                    await args.CompleteAsync(args.Message);

                    // we can also set arbitrary session state using this receiver
                    // the state is specific to the session, and not any particular message
                    await args.SetSessionStateAsync(Encoding.Default.GetBytes("some state"));

                    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
            }
        }