public async Task Scheduled_commands_are_reserialized_and_invoked_by_a_command_scheduler() { // arrange var bus = new FakeEventBus(); var shipmentId = Any.AlphanumericString(10); var repository = new InMemoryEventSourcedRepository <Order>(bus: bus); var scheduler = new InMemoryCommandScheduler <Order>(repository); bus.Subscribe(scheduler); var order = CreateOrder(); order.Apply(new ShipOn(shipDate: Clock.Now().AddMonths(1).Date) { ShipmentId = shipmentId }); await repository.Save(order); // act VirtualClock.Current.AdvanceBy(TimeSpan.FromDays(32)); //assert order = await repository.GetLatest(order.Id); var lastEvent = order.Events().Last(); lastEvent.Should().BeOfType <Order.Shipped>(); order.ShipmentId.Should().Be(shipmentId, "Properties should be transferred correctly from the serialized command"); }
public async Task EventBus_Should_Invoke_Event_Handlers_Implicit_Topic() { // Create handlers var state = new FakeState { Data = "A" }; var fakeHandler1 = new FakeEventHandler1(state); var fakeHandler2 = new FakeEventHandler2(state); // Create message broker var messageBroker = new FakeMessageBroker(); messageBroker.Subscribe(fakeHandler1); messageBroker.Subscribe(fakeHandler2); // Create service bus var eventBus = new FakeEventBus(messageBroker); eventBus.Subscribe(fakeHandler1); eventBus.Subscribe(fakeHandler2); // Publish to service bus var @event = new FakeIntegrationEvent("B"); await eventBus.PublishAsync(@event); // Assert Assert.Equal(@event.CreationDate, state.Date); Assert.Equal("B", state.Data); }
public override void When_storage_fails_then_no_events_are_published() { var order = new Order(); var bus = new FakeEventBus(); bus.Events <IEvent>().Subscribe(e => { throw new Exception("oops"); }); var repository = CreateRepository <Order>(() => { throw new Exception("oops!"); }); order .Apply(new AddItem { ProductName = "Widget", Price = 10m, Quantity = 2 }); try { repository.Save(order); } catch { } using (var db = new EventStoreDbContext()) { var events = db.Events.Where(e => e.AggregateId == order.Id).ToArray(); events.Count().Should().Be(0); } }
public void SetUp() { eventStoreDbTest = new EventStoreDbTest(); clockName = Any.CamelCaseName(); Clock.Reset(); disposables = new CompositeDisposable { Disposable.Create(() => eventStoreDbTest.TearDown()), Disposable.Create(Clock.Reset) }; var bus = new FakeEventBus(); orderRepository = new SqlEventSourcedRepository<Order>(bus); accountRepository = new SqlEventSourcedRepository<CustomerAccount>(bus); var configuration = new Configuration(); configuration.UseEventBus(bus) .UseDependency<IEventSourcedRepository<Order>>(t => orderRepository) .UseDependency<IEventSourcedRepository<CustomerAccount>>(t => accountRepository); ConfigureScheduler(configuration); disposables.Add(ConfigurationContext.Establish(configuration)); Console.WriteLine(new { clockName }); clockTrigger = configuration.Container.Resolve<ISchedulerClockTrigger>(); clockRepository = configuration.Container.Resolve<ISchedulerClockRepository>(); clockRepository.CreateClock(clockName, Clock.Now()); }
public async Task EventBus_Should_Invoke_Event_Handlers(TopicType topicType, string prefix) { // Topic name var topicName = topicType == TopicType.Explicit ? "my-topic" : null; // Create handlers var state = new FakeState { Data = "A" }; var fakeHandler1 = new FakeEventHandler1(state); var fakeHandler2 = new FakeEventHandler2(state); // Create message broker var messageBroker = new FakeMessageBroker(); messageBroker.Subscribe(fakeHandler1, topicName, prefix); messageBroker.Subscribe(fakeHandler2, topicName, prefix); // Create service bus var eventBus = new FakeEventBus(messageBroker); eventBus.Subscribe(fakeHandler1, topicName, prefix); eventBus.Subscribe(fakeHandler2, topicName, prefix); // Publish to service bus var @event = new FakeIntegrationEvent("B"); await eventBus.PublishAsync(@event, topicName, prefix); // Assert Assert.Equal(@event.CreationDate, state.Date); Assert.Equal("B", state.Data); }
public void When_the_aggregate_is_saved_then_the_reservation_is_confirmed() { // arrange var username = Any.Email(); var account = new CustomerAccount(); account.Apply(new RequestUserName { UserName = username, Principal = new Customer(username) }); var bus = new FakeEventBus(); bus.Subscribe(new UserNameConfirmer()); var repository = new SqlEventSourcedRepository <CustomerAccount>(bus); // act repository.Save(account); // assert using (var db = new ReservationServiceDbContext()) { db.Set <ReservedValue>() .Single(v => v.Value == username && v.Scope == "UserName") .Expiration .Should() .BeNull(); } }
public async Task Scheduled_commands_are_reserialized_and_invoked_by_a_command_scheduler() { // arrange var bus = new FakeEventBus(); var shipmentId = Any.AlphanumericString(10); var repository = new InMemoryEventSourcedRepository<Order>(bus: bus); var scheduler = new InMemoryCommandScheduler<Order>(repository); bus.Subscribe(scheduler); var order = CreateOrder(); order.Apply(new ShipOn(shipDate: Clock.Now().AddMonths(1).Date) { ShipmentId = shipmentId }); await repository.Save(order); // act VirtualClock.Current.AdvanceBy(TimeSpan.FromDays(32)); //assert order = await repository.GetLatest(order.Id); var lastEvent = order.Events().Last(); lastEvent.Should().BeOfType<Order.Shipped>(); order.ShipmentId.Should().Be(shipmentId, "Properties should be transferred correctly from the serialized command"); }
public void When_Subscribe_is_called_each_handler_interface_is_subscribed_once() { var bus = new FakeEventBus(); bus.Subscribe(new Handler_of_5_more_event_types()); bus.SubscribedEventTypes().Count().Should().Be(9); }
public void When_Subscribe_is_called_then_redundant_implementations_are_not_subscribed_more_than_once() { var bus = new FakeEventBus(); bus.Subscribe(new Handler_of_redundant_event_types()); bus.SubscribedEventTypes().Count().Should().Be(9); }
public void IProjectFrom_and_ITriggerProcessOn_interfaces_for_different_event_types_are_subscribed_on_the_same_handler_instance() { var bus = new FakeEventBus(); bus.Subscribe(new Projector_and_Trigger_from_different_event_types()); bus.SubscribedEventTypes().Count().Should().Be(2); }
public void When_Subscribe_is_called_with_a_handler_having_no_event_handler_implementations_then_it_throws() { var bus = new FakeEventBus(); bus.Invoking(b => b.Subscribe(new object())) .ShouldThrow <ArgumentException>() .And .Message.Should().Contain("does not implement any event handler interfaces"); }
public void IProjectFrom_and_ITriggerProcessOn_interfaces_for_same_event_type_are_subscribed_on_the_same_handler_instance() { var bus = new FakeEventBus(); bus.Subscribe(new Projector_and_Trigger_from_same_event_type()); bus.PublishAsync(new Order.Placed()).Wait(); bus.SubscribedEventTypes().Count().Should().Be(2); recordedEvents.Count().Should().Be(2); }
public void When_a_subscriber_subscribes_to_IEvent_then_they_receive_all_events() { var bus = new FakeEventBus(); var events = new List <object>(); bus.Events <IEvent>().Subscribe(events.Add); bus.PublishAsync(new Order.Cancelled()).Wait(); events.Last().Should().BeOfType <Order.Cancelled>(); }
public void When_a_subscriber_subscribes_to_events_for_one_aggregate_then_they_do_not_receive_events_for_other_aggregates() { var bus = new FakeEventBus(); var events = new List <object>(); bus.Events <Event <Order> >().Subscribe(events.Add); bus.PublishAsync(new Order.Cancelled(), new TestAggregate.SomeEvent()).Wait(); events.Last().Should().BeOfType <Order.Cancelled>(); }
public void GivenNoPreviousState_WhenPublishingSingleEvent_ThenEventsShouldBeStored() { // Arrange var eventBus = new FakeEventBus(); // Act eventBus.Publish(new SomethingHappened(1)); // Assert CollectionAssert.AreEqual(new object[] { new SomethingHappened(1) }, eventBus.Events); }
public void GivenNoPreviousState_WhenPublishingEvents_ThenEventsShouldBeStored() { // Arrange var eventBus = new FakeEventBus(); // Act eventBus.Publish((IEnumerable <IEvent>)(new IEvent[] { new SomethingHappened(1), new SomethingElseHappened(2) })); // Assert CollectionAssert.AreEqual(new object[] { new SomethingHappened(1), new SomethingElseHappened(2) }, eventBus.Events.ToArray()); }
public void All_commands_can_be_configured_for_SQL_scheduling_using_ScheduleCommandsUsingSqlScheduler() { var eventBus = new FakeEventBus(); eventBus.Subscribe(new SqlCommandScheduler(new Configuration().UseSqlEventStore())); eventBus.SubscribedEventTypes() .Should() .Contain(new[] { typeof(IScheduledCommand <Order>), typeof(IScheduledCommand <CustomerAccount>) }); }
public void All_commands_can_be_configured_for_SQL_scheduling_using_ScheduleCommandsUsingSqlScheduler() { var eventBus = new FakeEventBus(); eventBus.Subscribe(new SqlCommandScheduler(new Configuration().UseSqlEventStore())); eventBus.SubscribedEventTypes() .Should() .Contain(new[] { typeof (CommandScheduled<Order>), typeof (CommandScheduled<CustomerAccount>) }); }
public async Task ReadModelCatchup_only_queries_events_since_the_last_consumed_event_id() { var bus = new FakeEventBus(); var repository = new SqlEventSourcedRepository <Order>(bus); // save the order with no projectors running var order = new Order(); order.Apply(new AddItem { Price = 1m, ProductName = "Widget" }); await repository.Save(order); // subscribe one projector for catchup var projector1 = new Projector1(); using (var catchup = CreateReadModelCatchup(projector1)) { catchup.Progress.ForEachAsync(s => Console.WriteLine(s)); await catchup.Run(); } order.Apply(new AddItem { Price = 1m, ProductName = "Widget" }); await repository.Save(order); // subscribe both projectors var projector2 = new Projector2(); using (var catchup = CreateReadModelCatchup(projector1, projector2)) { catchup.Progress.ForEachAsync(s => Console.WriteLine(s)); await catchup.Run(); } projector1.CallCount.Should().Be(2, "A given event should only be passed to a given projector once"); projector2.CallCount.Should().Be(2, "A projector should be passed events it has not previously seen."); }
public override void SetUp() { base.SetUp(); using (VirtualClock.Start(DateTimeOffset.Now.AddMonths(1))) { disposables = new CompositeDisposable(); Settings.Sources = new ISettingsSource[] { new ConfigDirectorySettings(@"c:\dev\.config") }.Concat(Settings.Sources); serviceBusSettings = Settings.Get <ServiceBusSettings>(); serviceBusSettings.NamePrefix = "itscqrstests"; serviceBusSettings.ConfigureQueue = q => { q.AutoDeleteOnIdle = TimeSpan.FromMinutes(15); }; bus = new FakeEventBus(); orderRepository = new SqlEventSourcedRepository <Order>(bus); var configuration = new Configuration() .UseSqlEventStore(() => new EventStoreDbContext()) .UseEventBus(bus) .UseSqlCommandScheduling() .UseDependency <IEventSourcedRepository <Order> >(t => orderRepository); var clockName = Any.Paragraph(4); scheduler = new SqlCommandScheduler(configuration) { GetClockName = @event => clockName }; queueSender = new ServiceBusCommandQueueSender(serviceBusSettings) { MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromSeconds(30) }; disposables.Add(scheduler.Activity.Subscribe(s => Console.WriteLine("SqlCommandScheduler: " + s.ToJson()))); disposables.Add(queueSender.Messages.Subscribe(s => Console.WriteLine("ServiceBusCommandQueueSender: " + s.ToJson()))); disposables.Add(bus.Subscribe(scheduler)); disposables.Add(configuration); disposables.Add(ConfigurationContext.Establish(configuration)); } }
public override void SetUp() { base.SetUp(); using (VirtualClock.Start(DateTimeOffset.Now.AddMonths(1))) { disposables = new CompositeDisposable(); Settings.Sources = new ISettingsSource[] { new ConfigDirectorySettings(@"c:\dev\.config") }.Concat(Settings.Sources); serviceBusSettings = Settings.Get<ServiceBusSettings>(); serviceBusSettings.NamePrefix = "itscqrstests"; serviceBusSettings.ConfigureQueue = q => { q.AutoDeleteOnIdle = TimeSpan.FromMinutes(15); }; bus = new FakeEventBus(); orderRepository = new SqlEventSourcedRepository<Order>(bus); var configuration = new Configuration() .UseSqlEventStore(() => new EventStoreDbContext()) .UseEventBus(bus) .UseSqlCommandScheduling() .UseDependency<IEventSourcedRepository<Order>>(t => orderRepository); var clockName = Any.Paragraph(4); scheduler = new SqlCommandScheduler(configuration) { GetClockName = @event => clockName }; queueSender = new ServiceBusCommandQueueSender(serviceBusSettings) { MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromSeconds(30) }; disposables.Add(scheduler.Activity.Subscribe(s => Console.WriteLine("SqlCommandScheduler: " + s.ToJson()))); disposables.Add(queueSender.Messages.Subscribe(s => Console.WriteLine("ServiceBusCommandQueueSender: " + s.ToJson()))); disposables.Add(bus.Subscribe(scheduler)); disposables.Add(configuration); disposables.Add(ConfigurationContext.Establish(configuration)); } }
public void EventBus_Should_Remove_Event_Handlers(TopicType topicType, string prefix) { // Topic name var topicName = topicType == TopicType.Explicit ? "my-topic" : null; // Create handlers var state = new FakeState { Data = "A" }; var fakeHandler1 = new FakeEventHandler1(state); var fakeHandler2 = new FakeEventHandler2(state); // Create message broker var messageBroker = new FakeMessageBroker(); messageBroker.Subscribe(fakeHandler1, topicName, prefix); messageBroker.Subscribe(fakeHandler2, topicName, prefix); // Create service bus var eventBus = new FakeEventBus(messageBroker); eventBus.Subscribe(fakeHandler1, topicName, prefix); eventBus.Subscribe(fakeHandler2, topicName, prefix); // Remove handler eventBus.UnSubscribe(fakeHandler1, topicName, prefix); // Assert Assert.Single(eventBus.Topics); Assert.Single(eventBus.Topics.First().Value); // Remove handler eventBus.UnSubscribe(fakeHandler2, topicName, prefix); // Assert Assert.Empty(eventBus.Topics); }
public void Setup() { bus = new FakeEventBus(); aquirePrice = 100; processManager = new TrailingStopLossProcessManager(bus, aquirePrice); }
public void SetUp() { bus = new FakeEventBus(); recordedEvents = new List <RecordedEvent>(); }