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 Advancing_the_clock_blocks_until_triggered_commands_on_the_InMemoryCommandScheduler_are_completed() { VirtualClock.Start(); var repository = new InMemoryEventSourcedRepository <Order>(); var scheduler = new InMemoryCommandScheduler <Order>(repository); var aggregateId = Any.Guid(); await scheduler.Schedule(new CommandScheduled <Order> { Command = new CreateOrder(Any.FullName()) { AggregateId = aggregateId }, DueTime = Clock.Now().AddHours(1), AggregateId = aggregateId }); VirtualClock.Current.AdvanceBy(TimeSpan.FromDays(1)); var order = await repository.GetLatest(aggregateId); order.Should().NotBeNull(); }
private void Set(Func <IConfigureUpconverter, IBuildConfiguration> upconverterSetup) { if (isAlreadySetup) { return; } streamInfoContainer.ResetToNew(); var upconverterConfig = Configuration.Begin() .WithDefaultCollection() .WithDefaultStateFactory() .WithInterceptor(interceptorContext) .NeverUseThreadSafe() .WithNoEventPublisher() .WithAnyAppliersFrom(Assembly.GetExecutingAssembly()) .AndNoMoreAppliers(); var configuration = upconverterSetup(upconverterConfig) .Build(); var tempInMemRepo = new InMemoryEventSourcedRepository <int, IHoldHigherOrder>(configuration); var defaultValidator = tempInMemRepo.StateValidator; passThroughValidator.CurrentValidator = defaultValidator; sessionContainer.Setup(passThroughValidator, configuration); isAlreadySetup = true; }
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 Submit_CallsHandlerSavesAndPublishesEvents() { var repo = new InMemoryEventSourcedRepository(); var handler = new FakeCommandHandler(repo); var publisher = new Mock <IEventPublisher>(); var dispatcher = new CommandDispatcher(new[] { handler }, repo, publisher.Object); var id = Guid.NewGuid(); var updatedText = Guid.NewGuid().ToString(); dispatcher.Submit(new CreateFakeAggregate { Id = id }); dispatcher.Submit(new UpdateFakeAggregate { Id = id, Text = updatedText }); var aggreate = repo.GetById <FakeAggregate>(id); Assert.AreEqual(updatedText, aggreate.Text); publisher.Verify(f => f.PublishEvent(It.Is <IEvent>(e => e.GetType() == typeof(FakeAggregateCreated))), Times.Once); publisher.Verify(f => f.PublishEvent(It.Is <IEvent>(e => e.GetType() == typeof(FakeAggregateUpdated))), Times.Once); }
public void Setup(IHoldAllConfiguration configuration) { if (repository != null) { throw new Exception($"{nameof(repository)} already setup"); } repository = new InMemoryEventSourcedRepository <string, IHoldHigherOrder>(configuration); }
public static InMemoryEventSourcedRepository <TId, TState> WithEventInStream <TState, TId>( this InMemoryEventSourcedRepository <TId, TState> sut, object @event, TId streamId) { var currentEvents = sut[streamId]?.ToList() ?? new List <ItemWithType>(); currentEvents.Add(new ItemWithType(@event)); sut[streamId] = currentEvents.ToArray(); return(sut); }
public async Task When_one_command_triggers_another_command_via_a_consequenter_then_the_second_command_acquires_the_first_commands_clock() { // arrange var orderId = Any.Guid(); var customerId = Any.Guid(); var bus = new InProcessEventBus(); var orderRepository = new InMemoryEventSourcedRepository <Order>(bus: bus); await orderRepository.Save(new Order(new CreateOrder(Any.FullName()) { AggregateId = orderId, CustomerId = customerId }).Apply(new AddItem { ProductName = Any.Word(), Quantity = 1, Price = Any.Decimal(.01m, 10m) })); var customerRepository = new InMemoryEventSourcedRepository <CustomerAccount>(); await customerRepository.Save(new CustomerAccount(customerId).Apply(new ChangeEmailAddress(Any.Email()))); #pragma warning disable 618 bus.Subscribe(Consequenter.Create <Order.Shipped>(e => #pragma warning restore 618 { var order = orderRepository.GetLatest(e.AggregateId).Result; var customer = customerRepository.GetLatest(order.CustomerId).Result; customer.Apply(new SendOrderConfirmationEmail(order.OrderNumber)); customerRepository.Save(customer).Wait(); })); var shipDate = DateTimeOffset.Parse("2014-05-15 01:01:01"); var ship = new Ship(); // act using (CommandContext.Establish(ship, Clock.Create(() => shipDate))) { var order = await orderRepository.GetLatest(orderId); order.Apply(ship); await orderRepository.Save(order); } // assert var last = (await customerRepository.GetLatest(customerId)).Events().Last(); last.Should() .BeOfType <CustomerAccount.OrderShipConfirmationEmailSent>(); last.Timestamp.Should().Be(shipDate); }
public void InMemoryCommandScheduler_executes_scheduled_commands_immediately_if_no_due_time_is_specified() { // arrange var bus = new InProcessEventBus(); var repository = new InMemoryEventSourcedRepository <Order>(bus: bus); var scheduler = new InMemoryCommandScheduler <Order>(repository); bus.Subscribe(scheduler); var order = CreateOrder(); // act order.Apply(new ShipOn(Clock.Now().Subtract(TimeSpan.FromDays(2)))); repository.Save(order); //assert order = repository.GetLatest(order.Id); var lastEvent = order.Events().Last(); lastEvent.Should().BeOfType <Order.Shipped>(); }
public AggregateFixture(string name, object[] appliers = null) { var configuration = Configuration.Begin() .WithDefaultCollection() .WithDefaultStateFactory() .AlwaysUseThreadSafe() .WithNoEventPublisher() .WithAnyAppliersFromInstances((IEnumerable <object>)appliers ?? new List <object>()) .WithAnyAppliersFrom(Assembly.GetAssembly(typeof(CinemaAggregateState))) .AndNoMoreAppliers() .WithNoUpconverters() .Build(); this.name = name; correlationId = Guid.NewGuid(); CinemaFunctionalRepo = new InMemoryEventSourcedRepository <CinemaAggregateRootId, CinemaAggregateState>(configuration); ViewingFunctionalRepo = new InMemoryEventSourcedRepository <ViewingId, IViewingState>(configuration); cinemaId = new CinemaAggregateRootId(name); dateOfViewing = DateTime.Now.AddDays(3); }
public void Submit_CallsHandlerSavesAndPublishesEvents() { var repo = new InMemoryEventSourcedRepository(); var handler = new FakeCommandHandler(repo); var publisher = new Mock<IEventPublisher>(); var dispatcher = new CommandDispatcher(new[] { handler }, repo, publisher.Object); var id = Guid.NewGuid(); var updatedText = Guid.NewGuid().ToString(); dispatcher.Submit(new CreateFakeAggregate { Id = id }); dispatcher.Submit(new UpdateFakeAggregate { Id = id, Text = updatedText }); var aggreate = repo.GetById<FakeAggregate>(id); Assert.AreEqual(updatedText, aggreate.Text); publisher.Verify(f => f.PublishEvent(It.Is<IEvent>(e => e.GetType() == typeof(FakeAggregateCreated))), Times.Once); publisher.Verify(f => f.PublishEvent(It.Is<IEvent>(e => e.GetType() == typeof(FakeAggregateUpdated))), Times.Once); }
public async Task When_one_command_triggers_another_command_via_a_consequenter_then_the_second_command_acquires_the_first_commands_clock() { // arrange var orderId = Any.Guid(); var customerId = Any.Guid(); var bus = new InProcessEventBus(); var orderRepository = new InMemoryEventSourcedRepository<Order>(bus: bus); await orderRepository.Save(new Order(new CreateOrder(Any.FullName()) { AggregateId = orderId, CustomerId = customerId }).Apply(new AddItem { ProductName = Any.Word(), Quantity = 1, Price = Any.Decimal(.01m, 10m) })); var customerRepository = new InMemoryEventSourcedRepository<CustomerAccount>(); await customerRepository.Save(new CustomerAccount(customerId).Apply(new ChangeEmailAddress(Any.Email()))); bus.Subscribe(Consequenter.Create<Order.Shipped>(e => { var order = orderRepository.GetLatest(e.AggregateId).Result; var customer = customerRepository.GetLatest(order.CustomerId).Result; customer.Apply(new SendOrderConfirmationEmail(order.OrderNumber)); customerRepository.Save(customer).Wait(); })); var shipDate = DateTimeOffset.Parse("2014-05-15 01:01:01"); var ship = new Ship(); // act using (CommandContext.Establish(ship, Clock.Create(() => shipDate))) { var order = await orderRepository.GetLatest(orderId); order.Apply(ship); await orderRepository.Save(order); } // assert var last = (await customerRepository.GetLatest(customerId)).Events().Last(); last.Should() .BeOfType<CustomerAccount.OrderShipConfirmationEmailSent>(); last.Timestamp.Should().Be(shipDate); }
public async Task Advancing_the_clock_blocks_until_triggered_commands_on_the_InMemoryCommandScheduler_are_completed() { VirtualClock.Start(); var repository = new InMemoryEventSourcedRepository<Order>(); var scheduler = new InMemoryCommandScheduler<Order>(repository); var aggregateId = Any.Guid(); await scheduler.Schedule(new CommandScheduled<Order> { Command = new CreateOrder(Any.FullName()) { AggregateId = aggregateId }, DueTime = Clock.Now().AddHours(1), AggregateId = aggregateId }); VirtualClock.Current.AdvanceBy(TimeSpan.FromDays(1)); var order = await repository.GetLatest(aggregateId); order.Should().NotBeNull(); }
public async Task InMemoryCommandScheduler_executes_scheduled_commands_immediately_if_no_due_time_is_specified() { // arrange var bus = new InProcessEventBus(); var repository = new InMemoryEventSourcedRepository<Order>(bus: bus); var scheduler = new InMemoryCommandScheduler<Order>(repository); bus.Subscribe(scheduler); var order = CreateOrder(); // act order.Apply(new ShipOn(Clock.Now().Subtract(TimeSpan.FromDays(2)))); await repository.Save(order); await scheduler.Done(); //assert order = await repository.GetLatest(order.Id); var lastEvent = order.Events().Last(); lastEvent.Should().BeOfType<Order.Shipped>(); }