public async Task Recursive_scheduling_is_supported_when_scheduled_command_preconditions_are_satisfied_in_process() { var scenarioBuilder = CreateScenarioBuilder(); var scenario = scenarioBuilder.Prepare(); var customer = new CustomerAccount(); customer.Apply(new ChangeEmailAddress(Any.Email())); var scheduler = scenarioBuilder.Configuration.CommandScheduler <Order>(); var orderId = Any.Guid(); await scheduler.Schedule( orderId, new CreateOrder(Any.FullName()) { AggregateId = orderId }, deliveryDependsOn : customer.Events().First()); await Task.Delay(100); var order = scenario.GetLatest <Order>(orderId); order.Should().BeNull(); // act Console.WriteLine("SAVING"); scenario.Save(customer); order = scenario.GetLatest <Order>(orderId); order.Should().NotBeNull(); }
public async Task When_a_command_is_scheduled_but_the_event_that_triggered_it_was_not_successfully_written_then_the_command_is_not_applied() { // create a customer account var customer = new CustomerAccount(Any.Guid()) .Apply(new ChangeEmailAddress(Any.Email())); await Save(customer); var order = new Order(new CreateOrder(Any.FullName()) { CustomerId = customer.Id }); // act // cancel the order but don't save it order.Apply(new Cancel()); // assert // verify that the customer did not receive the scheduled NotifyOrderCanceled command customer = await Get <CustomerAccount>(customer.Id); customer.Events().Last().Should().BeOfType <CustomerAccount.EmailAddressChanged>(); using (var db = CommandSchedulerDbContext()) { db.ScheduledCommands .Where(c => c.AggregateId == customer.Id) .Should() .ContainSingle(c => c.AppliedTime == null); } }
public async Task Snapshotting_can_be_bypassed() { var snapshotRepository = new InMemorySnapshotRepository(); Configuration.Current.UseDependency <ISnapshotRepository>(_ => snapshotRepository); var account = new CustomerAccount() .Apply(new ChangeEmailAddress(Any.Email())) .Apply(new RequestSpam()) .Apply(new SendMarketingEmail()) .Apply(new SendOrderConfirmationEmail(Any.AlphanumericString(8, 8))); var eventSourcedRepository = CreateRepository <CustomerAccount>(); await eventSourcedRepository.Save(account); await snapshotRepository.SaveSnapshot(account); // act account = await eventSourcedRepository.GetLatest(account.Id); // assert account.Events().Count() .Should() .Be(4); }
public async Task Accessing_event_history_from_an_aggregate_instantiated_using_a_snapshot_throws() { var customerAccount = new CustomerAccount(new CustomerAccountSnapshot { AggregateId = Any.Guid(), Version = 10, EmailAddress = Any.Email() }); Action getEvents = () => customerAccount.Events(); getEvents.ShouldThrow <InvalidOperationException>() .And .Message .Should() .Contain("Aggregate was sourced from a snapshot, so event history is unavailable."); }
public void Accessing_event_history_from_an_aggregate_instantiated_using_a_snapshot_throws() { // arrange var account = new CustomerAccount() .Apply(new ChangeEmailAddress(Any.Email())); account.ConfirmSave(); var snapshot = account .CreateSnapshot(); snapshot.Version = 10; account = new CustomerAccount(snapshot); // act Action getEvents = () => account.Events(); // assert getEvents.ShouldThrow <InvalidOperationException>() .And .Message .Should() .Contain("Aggregate was sourced from a snapshot, so event history is unavailable."); }
public async Task When_a_command_is_scheduled_but_the_event_that_triggered_it_was_not_successfully_written_then_the_command_is_not_applied() { VirtualClock.Start(); // create a customer account var customer = new CustomerAccount(Any.Guid()) .Apply(new ChangeEmailAddress(Any.Email())); await accountRepository.Save(customer); var order = new Order(new CreateOrder(Any.FullName()) { CustomerId = customer.Id }); // act // cancel the order but don't save it order.Apply(new Cancel()); // assert // verify that the customer did not receive the scheduled NotifyOrderCanceled command customer = await accountRepository.GetLatest(customer.Id); customer.Events().Last().Should().BeOfType<CustomerAccount.EmailAddressChanged>(); using (var db = new CommandSchedulerDbContext()) { db.ScheduledCommands .Where(c => c.AggregateId == customer.Id) .Should() .ContainSingle(c => c.AppliedTime == null && c.DueTime == null); } }
public async Task A_scheduled_command_can_schedule_other_commands() { // ARRANGE var email = Any.Email(); Console.WriteLine(new { clockName, email }); var account = new CustomerAccount() .Apply(new ChangeEmailAddress(email)) .Apply(new SendMarketingEmailOn(Clock.Now().AddDays(1))) .Apply(new RequestSpam()); await accountRepository.Save(account); // ACT var result = await clockTrigger.AdvanceClock(clockName, TimeSpan.FromDays(10)); Console.WriteLine(result.ToLogString()); await SchedulerWorkComplete(); // ASSERT account = await accountRepository.GetLatest(account.Id); Console.WriteLine(account.Events() .Select(e => string.Format("{0}: {1}{2}\n", e.EventName(), e.Timestamp, e.IfTypeIs<IScheduledCommand<CustomerAccount>>() .Then(s => " --> DUE: " + s.DueTime) .ElseDefault())) .ToLogString()); account.Events() .OfType<CommandScheduled<CustomerAccount>>() .Count() .Should() .Be(3); account.Events() .Last() .Should() .BeOfType<CommandScheduled<CustomerAccount>>(); }
public async Task Accessing_event_history_from_an_aggregate_instantiated_using_a_snapshot_throws() { var customerAccount = new CustomerAccount(new CustomerAccountSnapshot { AggregateId = Any.Guid(), Version = 10, EmailAddress = Any.Email() }); Action getEvents = ()=> customerAccount.Events(); getEvents.ShouldThrow<InvalidOperationException>() .And .Message .Should() .Contain("Aggregate was sourced from a snapshot, so event history is unavailable."); }