public void when_sending_message_then_can_receive_it() { var sender = new TopicSender(this.Settings, this.Topic); Data data = new Data { Id = Guid.NewGuid(), Title = "Foo" }; Data received = null; using (var receiver = new SubscriptionReceiver(this.Settings, this.Topic, this.Subscription)) { var signal = new ManualResetEventSlim(); receiver.Start( m => { received = m.GetBody<Data>(); signal.Set(); return MessageReleaseAction.CompleteMessage; }); sender.SendAsync(() => new BrokeredMessage(data)); signal.Wait(); } Assert.NotNull(received); Assert.Equal(data.Id, received.Id); Assert.Equal(data.Title, received.Title); }
partial void OnCreateContainer(UnityContainer container) { var metadata = container.Resolve<IMetadataProvider>(); var serializer = container.Resolve<ITextSerializer>(); var commandBus = new CommandBus(new TopicSender(azureSettings.ServiceBus, Topics.Commands.Path), metadata, serializer); var topicSender = new TopicSender(azureSettings.ServiceBus, Topics.Events.Path); container.RegisterInstance<IMessageSender>(topicSender); var eventBus = new EventBus(topicSender, metadata, serializer); var commandProcessor = new CommandProcessor(new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, Topics.Commands.Subscriptions.All), serializer); container.RegisterInstance<ICommandBus>(commandBus); container.RegisterInstance<IEventBus>(eventBus); container.RegisterInstance<ICommandHandlerRegistry>(commandProcessor); container.RegisterInstance<IProcessor>("CommandProcessor", commandProcessor); RegisterRepository(container); RegisterEventProcessors(container); // message log var messageLogAccount = CloudStorageAccount.Parse(azureSettings.MessageLog.ConnectionString); container.RegisterInstance<IProcessor>("EventLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Events.Path, Topics.Events.Subscriptions.Log))); container.RegisterInstance<IProcessor>("CommandLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, Topics.Commands.Subscriptions.Log))); }
partial void OnCreateContainer(UnityContainer container) { var metadata = container.Resolve<IMetadataProvider>(); var serializer = container.Resolve<ITextSerializer>(); // blob var blobStorageAccount = CloudStorageAccount.Parse(azureSettings.BlobStorage.ConnectionString); container.RegisterInstance<IBlobStorage>(new SqlBlobStorage("BlobStorage")); var commandBus = new CommandBus(new TopicSender(azureSettings.ServiceBus, Topics.Commands.Path), metadata, serializer); var topicSender = new TopicSender(azureSettings.ServiceBus, Topics.Events.Path); container.RegisterInstance<IMessageSender>(topicSender); var eventBus = new EventBus(topicSender, metadata, serializer); var commandProcessor = new CommandProcessor(new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, "all", false, new SubscriptionReceiverInstrumentation("all", this.instrumentationEnabled)), serializer); container.RegisterInstance<ICommandBus>(commandBus); container.RegisterInstance<IEventBus>(eventBus); container.RegisterInstance<IProcessor>("CommandProcessor", commandProcessor); RegisterRepository(container); RegisterEventProcessors(container); RegisterCommandHandlers(container, commandProcessor); }
public void when_gets_transient_error_on_receive_then_retries() { var sender = new TopicSender(this.settings, this.topic); Data data = new Data { Id = Guid.NewGuid(), Title = "Foo" }; Data received = null; using (var receiver = new TestableSubscriptionReceiver(this.settings, this.topic, this.subscription, new Incremental(3, TimeSpan.Zero, TimeSpan.Zero), new Incremental(0, TimeSpan.Zero, TimeSpan.Zero))) { var attempt = 0; var currentDelegate = receiver.DoReceiveMessageDelegate; receiver.DoReceiveMessageDelegate = () => { if (attempt++ < 1) { throw new TimeoutException(); } return currentDelegate(); }; var signal = new ManualResetEventSlim(); receiver.MessageReceived += (o, e) => { received = e.Message.GetBody<Data>(); signal.Set(); }; receiver.Start(); sender.SendAsync(() => new BrokeredMessage(data)); Assert.True(signal.Wait(TimeSpan.FromSeconds(10)), "Test timed out"); } Assert.NotNull(received); Assert.Equal(data.Id, received.Id); Assert.Equal(data.Title, received.Title); }
partial void OnCreateContainer(UnityContainer container) { var metadata = container.Resolve<IMetadataProvider>(); var serializer = container.Resolve<ITextSerializer>(); // blob var blobStorageAccount = CloudStorageAccount.Parse(azureSettings.BlobStorage.ConnectionString); container.RegisterInstance<IBlobStorage>(new CloudBlobStorage(blobStorageAccount, azureSettings.BlobStorage.RootContainerName)); var commandBus = new CommandBus(new TopicSender(azureSettings.ServiceBus, Topics.Commands.Path), metadata, serializer); var eventsTopicSender = new TopicSender(azureSettings.ServiceBus, Topics.Events.Path); container.RegisterInstance<IMessageSender>("events", eventsTopicSender); container.RegisterInstance<IMessageSender>("orders", new TopicSender(azureSettings.ServiceBus, Topics.EventsOrders.Path)); container.RegisterInstance<IMessageSender>("seatsavailability", new TopicSender(azureSettings.ServiceBus, Topics.EventsAvailability.Path)); var eventBus = new EventBus(eventsTopicSender, metadata, serializer); var sessionlessCommandProcessor = new CommandProcessor(new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, Topics.Commands.Subscriptions.Sessionless, false, new SubscriptionReceiverInstrumentation(Topics.Commands.Subscriptions.Sessionless, this.instrumentationEnabled)), serializer); var seatsAvailabilityCommandProcessor = new CommandProcessor(new SessionSubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, Topics.Commands.Subscriptions.Seatsavailability, false, new SessionSubscriptionReceiverInstrumentation(Topics.Commands.Subscriptions.Seatsavailability, this.instrumentationEnabled)), serializer); var synchronousCommandBus = new SynchronousCommandBusDecorator(commandBus); container.RegisterInstance<ICommandBus>(synchronousCommandBus); container.RegisterInstance<IEventBus>(eventBus); container.RegisterInstance<IProcessor>("SessionlessCommandProcessor", sessionlessCommandProcessor); container.RegisterInstance<IProcessor>("SeatsAvailabilityCommandProcessor", seatsAvailabilityCommandProcessor); RegisterRepositories(container); RegisterEventProcessors(container); RegisterCommandHandlers(container, sessionlessCommandProcessor, seatsAvailabilityCommandProcessor); // handle order commands inline, as they do not have competition. synchronousCommandBus.Register(container.Resolve<ICommandHandler>("OrderCommandHandler")); // message log var messageLogAccount = CloudStorageAccount.Parse(azureSettings.MessageLog.ConnectionString); container.RegisterInstance<IProcessor>("EventLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Events.Path, Topics.Events.Subscriptions.Log))); container.RegisterInstance<IProcessor>("OrderEventLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.EventsOrders.Path, Topics.EventsOrders.Subscriptions.LogOrders))); container.RegisterInstance<IProcessor>("SeatsAvailabilityEventLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.EventsAvailability.Path, Topics.EventsAvailability.Subscriptions.LogAvail))); container.RegisterInstance<IProcessor>("CommandLogger", new AzureMessageLogListener( new AzureMessageLogWriter(messageLogAccount, azureSettings.MessageLog.TableName), new SubscriptionReceiver(azureSettings.ServiceBus, Topics.Commands.Path, Topics.Commands.Subscriptions.Log))); }
public void when_message_receivedthen_calls_process_message() { var waiter = new ManualResetEventSlim(); var sender = new TopicSender(this.Settings, this.Topic); var processor = new FakeProcessor( waiter, new SubscriptionReceiver(this.Settings, this.Topic, this.Subscription), new JsonTextSerializer()); processor.Start(); var stream = new MemoryStream(); new JsonTextSerializer().Serialize(new StreamWriter(stream), "Foo"); stream.Position = 0; sender.SendAsync(() => new BrokeredMessage(stream, true)); waiter.Wait(5000); Assert.NotNull(processor.Payload); }
public void when_processing_throws_then_sends_message_to_dead_letter() { var failCount = 0; var waiter = new ManualResetEventSlim(); var sender = new TopicSender(this.Settings, this.Topic); var processor = new Mock<MessageProcessor>( new SubscriptionReceiver(this.Settings, this.Topic, this.Subscription), new JsonTextSerializer()) { CallBase = true }; processor.Protected() .Setup("ProcessMessage", ItExpr.IsAny<string>(), ItExpr.IsAny<object>(), ItExpr.IsAny<string>(), ItExpr.IsAny<string>()) .Callback(() => { failCount++; if (failCount == 5) waiter.Set(); throw new ArgumentException(); }); processor.Object.Start(); var stream = new MemoryStream(); new JsonTextSerializer().Serialize(new StreamWriter(stream), "Foo"); stream.Position = 0; sender.SendAsync(() => new BrokeredMessage(stream, true)); waiter.Wait(5000); var deadReceiver = this.Settings.CreateMessageReceiver(this.Topic, this.Subscription); var deadMessage = deadReceiver.Receive(TimeSpan.FromSeconds(5)); processor.Object.Dispose(); Assert.NotNull(deadMessage); var data = new JsonTextSerializer().Deserialize(new StreamReader(deadMessage.GetBody<Stream>())); Assert.Equal("Foo", (string)data); }
static partial void OnCreateContainer(UnityContainer container) { var serializer = new JsonTextSerializer(); container.RegisterInstance<ITextSerializer>(serializer); var metadata = new StandardMetadataProvider(); container.RegisterInstance<IMetadataProvider>(metadata); var instrumentationEnabled = CloudConfigurationManager.GetSetting("InstrumentationEnabled") == "true"; // command bus var settings = InfrastructureSettings.Read(HttpContext.Current.Server.MapPath(@"~\bin\Settings.xml")); if (!Conference.Common.MaintenanceMode.IsInMaintainanceMode) { new ServiceBusConfig(settings.ServiceBus).Initialize(); } var commandBus = new CommandBus(new TopicSender(settings.ServiceBus, "conference/commands"), metadata, serializer); var synchronousCommandBus = new SynchronousCommandBusDecorator(commandBus); container.RegisterInstance<ICommandBus>(synchronousCommandBus); container.RegisterInstance<ICommandHandlerRegistry>(synchronousCommandBus); // blob var blobStorageAccount = CloudStorageAccount.Parse(settings.BlobStorage.ConnectionString); container.RegisterInstance<IBlobStorage>(new CloudBlobStorage(blobStorageAccount, settings.BlobStorage.RootContainerName)); // support for inline command processing container.RegisterType<ICommandHandler, OrderCommandHandler>("OrderCommandHandler"); container.RegisterType<ICommandHandler, ThirdPartyProcessorPaymentCommandHandler>("ThirdPartyProcessorPaymentCommandHandler"); container.RegisterType<ICommandHandler, SeatAssignmentsHandler>("SeatAssignmentsHandler"); container.RegisterType<DbContext, PaymentsDbContext>("payments", new TransientLifetimeManager(), new InjectionConstructor("Payments")); container.RegisterType<IDataContext<ThirdPartyProcessorPayment>, SqlDataContext<ThirdPartyProcessorPayment>>( new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<Func<DbContext>>("payments"), typeof(IEventBus))); container.RegisterType<IPricingService, PricingService>(new ContainerControlledLifetimeManager()); var topicSender = new TopicSender(settings.ServiceBus, "conference/events"); container.RegisterInstance<IMessageSender>(topicSender); var eventBus = new EventBus(topicSender, metadata, serializer); container.RegisterInstance<IEventBus>(eventBus); var eventSourcingAccount = CloudStorageAccount.Parse(settings.EventSourcing.ConnectionString); var eventStore = new EventStore(eventSourcingAccount, settings.EventSourcing.OrdersTableName); container.RegisterInstance<IEventStore>(eventStore); container.RegisterInstance<IPendingEventsQueue>(eventStore); container.RegisterType<IEventStoreBusPublisher, EventStoreBusPublisher>( new ContainerControlledLifetimeManager(), new InjectionConstructor( new TopicSender(settings.ServiceBus, "conference/eventsOrders"), typeof(IPendingEventsQueue), new EventStoreBusPublisherInstrumentation("web.public - orders", instrumentationEnabled))); container.RegisterType( typeof(IEventSourcedRepository<>), typeof(AzureEventSourcedRepository<>), new ContainerControlledLifetimeManager(), new InjectionConstructor(typeof(IEventStore), typeof(IEventStoreBusPublisher), typeof(ITextSerializer), typeof(IMetadataProvider), new InjectionParameter<ObjectCache>(null))); // to satisfy the IProcessor requirements. container.RegisterType<IProcessor, PublisherProcessorAdapter>("EventStoreBusPublisher", new ContainerControlledLifetimeManager()); }
public void when_message_fails_to_deserialize_then_dead_letters_message() { var waiter = new ManualResetEventSlim(); var sender = new TopicSender(this.Settings, this.Topic); var processor = new FakeProcessor( waiter, new SubscriptionReceiver(this.Settings, this.Topic, this.Subscription), new JsonTextSerializer()); processor.Start(); var data = new JsonTextSerializer().Serialize(new Data()); data = data.Replace(typeof(Data).FullName, "Some.TypeName.Cannot.Resolve"); var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)); stream.Position = 0; sender.SendAsync(() => new BrokeredMessage(stream, true)); waiter.Wait(5000); var deadReceiver = this.Settings.CreateMessageReceiver(this.Topic, this.Subscription); var deadMessage = deadReceiver.Receive(TimeSpan.FromSeconds(5)); processor.Dispose(); Assert.NotNull(deadMessage); var payload = new StreamReader(deadMessage.GetBody<Stream>()).ReadToEnd(); Assert.Contains("Some.TypeName.Cannot.Resolve", payload); }
public void when_gets_transient_error_several_times_on_receive_then_retries_until_failure() { var attempt = 0; var sender = new TopicSender(this.settings, this.topic); Data data = new Data { Id = Guid.NewGuid(), Title = "Foo" }; Data received = null; using (var receiver = new TestableSubscriptionReceiver(this.settings, this.topic, this.subscription, new Incremental(3, TimeSpan.Zero, TimeSpan.Zero), new Incremental(0, TimeSpan.Zero, TimeSpan.Zero))) { var signal = new ManualResetEventSlim(); receiver.DoReceiveMessageDelegate = () => { if (attempt++ == 3) { signal.Set(); } throw new TimeoutException(); }; receiver.MessageReceived += (o, e) => { received = e.Message.GetBody<Data>(); }; receiver.Start(); sender.SendAsync(() => new BrokeredMessage(data)); Assert.True(signal.Wait(TimeSpan.FromSeconds(10)), "Test timed out"); Thread.Sleep(TimeSpan.FromMilliseconds(500)); } Thread.Sleep(TimeSpan.FromSeconds(1)); Assert.Null(received); }
public void when_creating_processor_then_receives_from_specified_subscription() { this.sut.Initialize(); var waiter = new ManualResetEventSlim(); var handler = new Mock<IEventHandler<AnEvent>>(); var serializer = new JsonTextSerializer(); var ev = new AnEvent(); handler.Setup(x => x.Handle(It.IsAny<AnEvent>())) .Callback(() => waiter.Set()); var processor = this.sut.CreateEventProcessor("log", handler.Object, serializer); processor.Start(); var sender = new TopicSender(this.settings, this.settings.Topics.First(t => t.Path.StartsWith("conference/events")).Path); var bus = new EventBus(sender, new StandardMetadataProvider(), serializer); bus.Publish(ev); waiter.Wait(5000); handler.Verify(x => x.Handle(It.Is<AnEvent>(e => e.SourceId == ev.SourceId))); }