public void Should_extract_body_as_stream_when_configured(string transportEncoding) { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var extensions = new TransportExtensions <AzureServiceBusTransport>(settings); extensions.BrokeredMessageBodyType(SupportedBrokeredMessageBodyTypes.Stream); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.Write("Whatever"); writer.Flush(); stream.Position = 0; var brokeredMessage = new BrokeredMessage(stream); brokeredMessage.Properties[BrokeredMessageHeaders.TransportEncoding] = transportEncoding; var incomingMessage = converter.Convert(brokeredMessage); var body = Encoding.UTF8.GetString(incomingMessage.Body); Assert.AreEqual("Whatever", body); }
public async Task Triggers_critical_error_when_receiver_cannot_be_started() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); settings.Set <TopologySettings>(new TopologySettings()); var namespacesDefinition = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces); namespacesDefinition.Add("namespace", AzureServiceBusConnectionString.Value, NamespacePurpose.Partitioning); // setup the infrastructure var namespaceManagerCreator = new NamespaceManagerCreator(settings); var namespaceLifecycleManager = new NamespaceManagerLifeCycleManagerInternal(namespaceManagerCreator); var messagingFactoryCreator = new MessagingFactoryCreator(namespaceLifecycleManager, settings); var messagingFactoryLifeCycleManager = new MessagingFactoryLifeCycleManager(messagingFactoryCreator, settings); var messageReceiverCreator = new MessageReceiverCreator(messagingFactoryLifeCycleManager, settings); var clientEntityLifeCycleManager = new MessageReceiverLifeCycleManager(messageReceiverCreator, settings); var brokeredMessageConverter = new BrokeredMessagesToIncomingMessagesConverter(settings, new PassThroughMapper(settings)); // perform the test var notifier = new MessageReceiverNotifier(clientEntityLifeCycleManager, brokeredMessageConverter, BuildMessageReceiverNotifierSettings(settings)); var completed = new AsyncManualResetEvent(false); var error = new AsyncManualResetEvent(false); Exception ex = null; var received = false; notifier.Initialize(new EntityInfoInternal { Path = "myqueue", Namespace = new RuntimeNamespaceInfo("namespace", AzureServiceBusConnectionString.Value) }, (message, context) => { received = true; completed.Set(); return(TaskEx.Completed); }, null, exception => { ex = exception; error.Set(); }, null, 1); notifier.Start(); await Task.WhenAny(completed.WaitAsync(cts.Token).IgnoreCancellation(), error.WaitAsync(cts.Token).IgnoreCancellation()); // validate Assert.IsFalse(received); Assert.IsNotNull(ex); }
public void Should_throw_for_a_message_without_transport_encoding_header_supplied_and_actual_body_type_other_than_default() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var brokeredMessage = new BrokeredMessage("non-default-type"); Assert.Throws <UnsupportedBrokeredMessageBodyTypeException>(() => converter.Convert(brokeredMessage)); }
public void Should_throw_for_a_message_with_unknown_transport_encoding_header_supplied() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var brokeredMessage = new BrokeredMessage("non-default-type"); brokeredMessage.Properties[BrokeredMessageHeaders.TransportEncoding] = "unknown"; Assert.Throws <UnsupportedBrokeredMessageBodyTypeException>(() => converter.Convert(brokeredMessage)); }
public void Should_copy_properties_into_the_headers() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var brokeredMessage = new BrokeredMessage(); brokeredMessage.Properties.Add("my-test-prop", "myvalue"); var incomingMessage = converter.Convert(brokeredMessage); Assert.IsTrue(incomingMessage.Headers.Any(h => h.Key == "my-test-prop" && h.Value == "myvalue")); }
public void Should_extract_body_as_byte_array_by_default() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var bytes = Encoding.UTF8.GetBytes("Whatever"); var brokeredMessage = new BrokeredMessage(bytes); var incomingMessage = converter.Convert(brokeredMessage); var body = Encoding.UTF8.GetString(incomingMessage.Body); Assert.AreEqual(body, "Whatever"); }
public void Should_not_propagate_transport_encoding_header_from_brokered_message() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var bytes = Encoding.UTF8.GetBytes("Whatever"); var brokeredMessage = new BrokeredMessage(bytes); brokeredMessage.Properties[BrokeredMessageHeaders.TransportEncoding] = "wcf/byte-array"; var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var incomingMessageDetails = converter.Convert(brokeredMessage); CollectionAssert.DoesNotContain(incomingMessageDetails.Headers, BrokeredMessageHeaders.TransportEncoding, $"Headers should not contain `{BrokeredMessageHeaders.TransportEncoding}`, but it was found."); }
public void Should_copy_the_message_id() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var brokeredMessage = new BrokeredMessage { MessageId = "someid" }; var incomingMessage = converter.Convert(brokeredMessage); Assert.IsTrue(incomingMessage.MessageId == "someid"); }
public void Should_return_empty_byte_array_for_octectstream_encoded_message() { var message = new BrokeredMessage(null); message.Properties[BrokeredMessageHeaders.TransportEncoding] = "application/octect-stream"; var settings = new SettingsHolder(); settings.Set(WellKnownConfigurationKeys.Topology.Addressing.Namespaces, new NamespaceConfigurations()); settings.Set(WellKnownConfigurationKeys.Serialization.BrokeredMessageBodyType, SupportedBrokeredMessageBodyTypes.Stream); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new DefaultConnectionStringToNamespaceAliasMapper(settings)); var converted = converter.Convert(message); Assert.AreEqual(Array.Empty <byte>(), converted.Body); }
public void Should_complete_replyto_address_if_not_present_in_headers() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MappedMyQueue")); var brokeredMessage = new BrokeredMessage(new byte[] { }) { ReplyTo = "MyQueue" }; var incomingMessage = converter.Convert(brokeredMessage); Assert.IsTrue(incomingMessage.Headers.ContainsKey(Headers.ReplyToAddress)); Assert.AreEqual("MappedMyQueue", incomingMessage.Headers[Headers.ReplyToAddress]); }
public async Task Can_start_stop_and_restart_notifier() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); settings.Set <TopologySettings>(new TopologySettings()); var namespacesDefinition = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces); namespacesDefinition.Add("namespace", AzureServiceBusConnectionString.Value, NamespacePurpose.Partitioning); // setup the infrastructure var namespaceManagerCreator = new NamespaceManagerCreator(settings); var namespaceLifecycleManager = new NamespaceManagerLifeCycleManagerInternal(namespaceManagerCreator); var messagingFactoryCreator = new MessagingFactoryCreator(namespaceLifecycleManager, settings); var messagingFactoryLifeCycleManager = new MessagingFactoryLifeCycleManager(messagingFactoryCreator, settings); var messageReceiverCreator = new MessageReceiverCreator(messagingFactoryLifeCycleManager, settings); var clientEntityLifeCycleManager = new MessageReceiverLifeCycleManager(messageReceiverCreator, settings); var creator = new AzureServiceBusQueueCreator(settings.Get <TopologySettings>().QueueSettings, settings); var brokeredMessageConverter = new BrokeredMessagesToIncomingMessagesConverter(settings, new PassThroughMapper(settings)); // create the queue var namespaceManager = namespaceLifecycleManager.Get("namespace"); await creator.Create("myqueue", namespaceManager); // perform the test var notifier = new MessageReceiverNotifier(clientEntityLifeCycleManager, brokeredMessageConverter, BuildMessageReceiverNotifierSettings(settings)); notifier.Initialize(new EntityInfoInternal { Path = "myqueue", Namespace = new RuntimeNamespaceInfo("namespace", AzureServiceBusConnectionString.Value) }, (message, context) => TaskEx.Completed, null, null, null, 10); notifier.Start(); await notifier.Stop(); notifier.Start(); await notifier.Stop(); //cleanup await namespaceManager.DeleteQueue("myqueue"); }
public void Should_complete_timetobereceived_if_not_present_in_headers() { // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var converter = new BrokeredMessagesToIncomingMessagesConverter(settings, new FakeMapper(settings, "MyQueue", "MyQueue")); var timespan = TimeSpan.FromHours(1); var brokeredMessage = new BrokeredMessage(new byte[] { }) { TimeToLive = timespan }; var incomingMessage = converter.Convert(brokeredMessage); Assert.IsTrue(incomingMessage.Headers.ContainsKey(Headers.TimeToBeReceived)); Assert.AreEqual(timespan.ToString(), incomingMessage.Headers[Headers.TimeToBeReceived]); }
public async Task Can_receive_messages_with_prefetch_fast() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); var namespacesDefinition = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces); namespacesDefinition.Add("namespace", AzureServiceBusConnectionString.Value, NamespacePurpose.Partitioning); settings.Set(WellKnownConfigurationKeys.Connectivity.MessageReceivers.PrefetchCount, 500); settings.Set(WellKnownConfigurationKeys.Connectivity.MessageReceivers.ReceiveMode, ReceiveMode.PeekLock); settings.Set(WellKnownConfigurationKeys.Connectivity.SendViaReceiveQueue, true); // default values set by DefaultConfigurationValues.Apply - shouldn't hardcode those here, so OK to use settings var messageReceiverNotifierSettings = new MessageReceiverNotifierSettings( ReceiveMode.PeekLock, settings.HasExplicitValue <TransportTransactionMode>() ? settings.Get <TransportTransactionMode>() : settings.SupportedTransactionMode(), settings.Get <TimeSpan>(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout), settings.Get <int>(WellKnownConfigurationKeys.Connectivity.NumberOfClientsPerEntity)); // setup the infrastructure var namespaceManagerCreator = new NamespaceManagerCreator(settings); var namespaceLifeCycleManager = new NamespaceManagerLifeCycleManagerInternal(namespaceManagerCreator); var messagingFactoryCreator = new MessagingFactoryCreator(namespaceLifeCycleManager, settings); var messagingFactoryLifeCycleManager = new MessagingFactoryLifeCycleManager(messagingFactoryCreator, settings); var messageReceiverCreator = new MessageReceiverCreator(messagingFactoryLifeCycleManager, settings); var creator = new AzureServiceBusQueueCreator(new TopologyQueueSettings(), settings); var brokeredMessageConverter = new BrokeredMessagesToIncomingMessagesConverter(settings, new PassThroughMapper(settings)); // create the queue var namespaceManager = namespaceLifeCycleManager.Get("namespace"); var queue = await creator.Create("myqueue", namespaceManager); var receivedMessages = 0; var completed = new AsyncManualResetEvent(false); // sending messages to the queue var senderFactory = new MessageSenderCreator(messagingFactoryLifeCycleManager, settings); var sender = await senderFactory.Create("myqueue", null, "namespace"); var counter = 0; var tasks = new List <Task>(); for (var j = 0; j < 10; j++) { var batch = new List <BrokeredMessage>(); for (var i = 0; i < 100; i++) { batch.Add(new BrokeredMessage(Encoding.UTF8.GetBytes("Whatever" + counter))); counter++; } tasks.Add(sender.RetryOnThrottleAsync(s => s.SendBatch(batch), s => s.SendBatch(batch.Select(x => x.Clone())), TimeSpan.FromSeconds(10), 5)); } await Task.WhenAll(tasks); var faulted = tasks.Count(task => task.IsFaulted); var expected = 1000 - faulted; // sending messages to the queue is done var notifier = new MessageReceiverNotifier(messageReceiverCreator, brokeredMessageConverter, messageReceiverNotifierSettings); notifier.Initialize(new EntityInfoInternal { Path = "myqueue", Namespace = new RuntimeNamespaceInfo("namespace", AzureServiceBusConnectionString.Value) }, (message, context) => { var numberOfMessages = Interlocked.Increment(ref receivedMessages); if (numberOfMessages == expected) { completed.Set(); } return(TaskEx.Completed); }, null, null, null, 32); var sw = new Stopwatch(); sw.Start(); notifier.Start(); await completed.WaitAsync(cts.Token).IgnoreCancellation(); sw.Stop(); await notifier.Stop(); Assert.IsTrue(receivedMessages == expected); Console.WriteLine($"Receiving {receivedMessages} messages took {sw.ElapsedMilliseconds} milliseconds"); Console.WriteLine("Total of {0} msgs / second", (double)receivedMessages / sw.ElapsedMilliseconds * 1000); // make sure messages are auto-completed Assert.That(queue.MessageCount, Is.EqualTo(0), "Messages where not completed!"); //cleanup await namespaceManager.DeleteQueue("myqueue"); }
public async Task Should_have_rolled_back_message_to_error_queue() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); settings.Set(new TopologySettings()); var namespacesDefinition = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces); namespacesDefinition.Add("namespace", AzureServiceBusConnectionString.Value, NamespacePurpose.Partitioning); // set lock duration on a queue to 5 seconds and emulate message processing that takes longer than that, but less than AutoRenewTimeout settings.Get <TopologySettings>().QueueSettings.LockDuration = TimeSpan.FromSeconds(2); settings.Set(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout, TimeSpan.FromSeconds(5)); // default values set by DefaultConfigurationValues.Apply - shouldn't hardcode those here, so OK to use settings var messageReceiverNotifierSettings = new MessageReceiverNotifierSettings( ReceiveMode.PeekLock, TransportTransactionMode.SendsAtomicWithReceive, settings.Get <TimeSpan>(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout), settings.Get <int>(WellKnownConfigurationKeys.Connectivity.NumberOfClientsPerEntity)); // setup the infrastructure var namespaceManagerCreator = new NamespaceManagerCreator(settings); var namespaceLifecycleManager = new NamespaceManagerLifeCycleManagerInternal(namespaceManagerCreator); var messagingFactoryCreator = new MessagingFactoryCreator(namespaceLifecycleManager, settings); var messagingFactoryLifeCycleManager = new MessagingFactoryLifeCycleManager(messagingFactoryCreator, settings); var messageReceiverCreator = new MessageReceiverCreator(messagingFactoryLifeCycleManager, settings); var creator = new AzureServiceBusQueueCreator(settings.Get <TopologySettings>().QueueSettings, settings); var brokeredMessageConverter = new BrokeredMessagesToIncomingMessagesConverter(settings, new PassThroughMapper(settings)); // create the queue var namespaceManager = namespaceLifecycleManager.Get("namespace"); await creator.Create("completionfailure", namespaceManager); var completed = new AsyncManualResetEvent(false); // sending messages to the queue var senderFactory = new MessageSenderCreator(messagingFactoryLifeCycleManager, settings); var sender = await senderFactory.Create("completionfailure", null, "namespace"); var messageToSend = new BrokeredMessage(Encoding.UTF8.GetBytes("Whatever")) { MessageId = Guid.NewGuid().ToString() }; await sender.Send(messageToSend); // sending messages to the queue is done var rolledBack = new RollbackDetection(); var notifier = new MessageReceiverNotifier(messageReceiverCreator, brokeredMessageConverter, messageReceiverNotifierSettings); notifier.Initialize(new EntityInfoInternal { Path = "completionfailure", Namespace = new RuntimeNamespaceInfo("namespace", AzureServiceBusConnectionString.Value) }, (message, context) => { if (message.MessageId == messageToSend.MessageId) { Transaction.Current.EnlistVolatile(new EmulateCompletionFailure(), EnlistmentOptions.EnlistDuringPrepareRequired); throw new Exception("Force processing failure"); } return(TaskEx.Completed); }, null, null, context => { if (context.Message.MessageId == messageToSend.MessageId) { Transaction.Current.EnlistVolatile(rolledBack, EnlistmentOptions.None); completed.Set(); } return(Task.FromResult(ErrorHandleResult.Handled)); }, 1); var sw = new Stopwatch(); sw.Start(); notifier.Start(); await completed.WaitAsync(cts.Token).IgnoreCancellation(); sw.Stop(); await notifier.Stop(); Assert.IsTrue(rolledBack.RolledBack, "Should have rolled back the error message."); Console.WriteLine($"Callback processing took {sw.ElapsedMilliseconds} milliseconds"); //cleanup await namespaceManager.DeleteQueue("completionfailure"); }
public async Task AutoRenewTimeout_will_extend_lock_for_processing_to_finish() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); // default settings var settings = DefaultConfigurationValues.Apply(SettingsHolderFactory.BuildWithSerializer()); settings.Set(new TopologySettings()); var namespacesDefinition = settings.Get <NamespaceConfigurations>(WellKnownConfigurationKeys.Topology.Addressing.Namespaces); namespacesDefinition.Add("namespace", AzureServiceBusConnectionString.Value, NamespacePurpose.Partitioning); // set lock duration on a queue to 5 seconds and emulate message processing that takes longer than that, but less than AutoRenewTimeout settings.Get <TopologySettings>().QueueSettings.LockDuration = TimeSpan.FromSeconds(2); settings.Set(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout, TimeSpan.FromSeconds(5)); // default values set by DefaultConfigurationValues.Apply - shouldn't hardcode those here, so OK to use settings var messageReceiverNotifierSettings = new MessageReceiverNotifierSettings( ReceiveMode.PeekLock, settings.HasExplicitValue <TransportTransactionMode>() ? settings.Get <TransportTransactionMode>() : settings.SupportedTransactionMode(), settings.Get <TimeSpan>(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout), settings.Get <int>(WellKnownConfigurationKeys.Connectivity.NumberOfClientsPerEntity)); // setup the infrastructure var namespaceManagerCreator = new NamespaceManagerCreator(settings); var namespaceLifecycleManager = new NamespaceManagerLifeCycleManagerInternal(namespaceManagerCreator); var messagingFactoryCreator = new MessagingFactoryCreator(namespaceLifecycleManager, settings); var messagingFactoryLifeCycleManager = new MessagingFactoryLifeCycleManager(messagingFactoryCreator, settings); var messageReceiverCreator = new MessageReceiverCreator(messagingFactoryLifeCycleManager, settings); var creator = new AzureServiceBusQueueCreator(settings.Get <TopologySettings>().QueueSettings, settings); var brokeredMessageConverter = new BrokeredMessagesToIncomingMessagesConverter(settings, new PassThroughMapper(settings)); // create the queue var namespaceManager = namespaceLifecycleManager.Get("namespace"); await creator.Create("autorenewtimeout", namespaceManager); var receivedMessages = 0; var completed = new AsyncManualResetEvent(false); // sending messages to the queue var senderFactory = new MessageSenderCreator(messagingFactoryLifeCycleManager, settings); var sender = await senderFactory.Create("autorenewtimeout", null, "namespace"); var messageToSend = new BrokeredMessage(Encoding.UTF8.GetBytes("Whatever")) { MessageId = Guid.NewGuid().ToString() }; await sender.Send(messageToSend); // sending messages to the queue is done var notifier = new MessageReceiverNotifier(messageReceiverCreator, brokeredMessageConverter, messageReceiverNotifierSettings); notifier.Initialize(new EntityInfoInternal { Path = "autorenewtimeout", Namespace = new RuntimeNamespaceInfo("namespace", AzureServiceBusConnectionString.Value) }, async(message, context) => { if (message.MessageId == messageToSend.MessageId) { Interlocked.Increment(ref receivedMessages); if (receivedMessages > 1) { Assert.Fail("Callback should only receive one message once, but it did more than that."); } await Task.Delay(TimeSpan.FromSeconds(5), cts.Token); completed.Set(); } }, null, null, null, 1); var sw = new Stopwatch(); sw.Start(); notifier.Start(); await completed.WaitAsync(cts.Token).IgnoreCancellation(); sw.Stop(); await notifier.Stop(); Assert.AreEqual(1, receivedMessages, $"Expected to receive message once, but got {receivedMessages}."); Console.WriteLine($"Callback processing took {sw.ElapsedMilliseconds} milliseconds"); //cleanup await namespaceManager.DeleteQueue("autorenewtimeout"); }