public override async Task Scheduled_commands_with_no_due_time_are_delivered_at_Clock_Now_when_delivery_is_deferred() { // arrange var deliveredTime = new DateTimeOffset(); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); Configuration .Current .UseCommandHandler <NonEventSourcedCommandTarget, TestCommand>(async(_, __) => deliveredTime = Clock.Now()); // act await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = false }, dueTime : null); await AdvanceClock( clockName : clockName, by : 1.Hours()); // assert deliveredTime .Should() .Be(Clock.Now()); }
public async Task When_the_VirtualClock_is_advanced_past_a_commands_due_time_then_in_EnactCommand_ClockNow_returns_the_commands_due_time() { var dueTime = DateTimeOffset.Parse("2019-09-01 +00:00"); VirtualClock.Start(DateTimeOffset.Parse("2019-01-01 +00:00")); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); var configuration = Configuration.Current; await configuration.Store <NonEventSourcedCommandTarget>().Put(target); var clockNowAtCommandDeliveryTime = default(DateTimeOffset); configuration.UseCommandHandler <NonEventSourcedCommandTarget, TestCommand>( enactCommand: async(_, __) => { clockNowAtCommandDeliveryTime = Clock.Now(); }); var scheduler = configuration.CommandScheduler <NonEventSourcedCommandTarget>(); await scheduler.Schedule(target.Id, new TestCommand(), dueTime : dueTime); VirtualClock.Current.AdvanceBy(365.Days()); clockNowAtCommandDeliveryTime.Should().Be(dueTime); }
public override async Task Scheduled_commands_are_delivered_immediately_if_past_due_per_the_domain_clock() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(), Clock.Now().AddMinutes(-2)); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task Scheduled_commands_are_delivered_immediately_if_past_due_per_the_domain_clock() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(), Clock.Now().AddMinutes(-2)); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task When_a_clock_is_advanced_then_commands_are_not_triggered_that_have_not_become_due() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(), Clock.Now().AddDays(2)); await AdvanceClock(TimeSpan.FromDays(1.1)); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(0); }
public override async Task When_a_clock_is_advanced_its_associated_commands_are_triggered() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); await Schedule(target.Id, new TestCommand(), Clock.Now().AddDays(1)); // act await AdvanceClock(25.Hours()); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task When_a_clock_is_advanced_then_commands_are_not_triggered_that_have_not_become_due() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(), Clock.Now().AddDays(2)); await AdvanceClock(TimeSpan.FromDays(1.1)); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(0); }
public override async Task Scheduled_commands_are_delivered_immediately_if_past_due_per_the_scheduler_clock() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); var schedulerClockTime = DateTimeOffset.Parse("2016-02-13 03:03:48 PM"); // act await Schedule(target.Id, new TestCommand(), schedulerClockTime.AddMinutes(-2)); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task When_a_clock_is_advanced_its_associated_commands_are_triggered() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); await Schedule(target.Id, new TestCommand(), Clock.Now().AddDays(1)); // act await AdvanceClock(25.Hours()); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task When_a_command_is_scheduled_but_an_exception_is_thrown_in_a_handler_then_an_error_is_recorded() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(isValid : false)); //assert using (var db = CommandSchedulerDbContext()) { var aggregateId = target.Id.ToGuidV3(); var error = db.Errors.Single(e => e.ScheduledCommand.AggregateId == aggregateId); error.Error.Should().Contain("CommandValidationException"); } }
public override async Task When_command_is_durable_but_immediate_delivery_succeeds_then_it_is_not_redelivered() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand { RequiresDurableScheduling = true }); await AdvanceClock(2.Days()); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public async Task When_a_command_is_delivered_and_throws_during_clock_advance_then_other_commands_are_still_delivered() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { OnEnactCommand = async(commandTarget, command) => { await Task.Yield(); if (command.ETag == "first") { throw new Exception("oops!"); } } }; var store = Configuration.Current.Store <NonEventSourcedCommandTarget>(); await store.Put(target); VirtualClock.Start(); // act var scheduler = Configuration.Current.CommandScheduler <NonEventSourcedCommandTarget>(); await scheduler.Schedule(target.Id, new TestCommand(etag : "first"), Clock.Now().AddMinutes(1)); await scheduler.Schedule(target.Id, new TestCommand(etag : "second"), Clock.Now().AddMinutes(2)); VirtualClock.Current.AdvanceBy(1.Hours()); // assert target = await store.Get(target.Id); target.CommandsEnacted .Select(c => c.ETag) .Should() .Contain(etag => etag == "second"); }
public override async Task A_command_handler_can_cancel_a_scheduled_command_after_it_fails() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { OnHandleScheduledCommandError = async(commandTarget, failed) => failed.Cancel() }; await Save(target); // act await Schedule(target.Id, new TestCommand(isValid : false), Clock.Now().AddMinutes(2)); await AdvanceClock(5.Minutes()); //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsFailed.Should().HaveCount(1); }
public override async Task Immediately_scheduled_commands_triggered_by_a_scheduled_command_have_their_due_time_set_to_the_causative_command_clock() { // arrange var deliveredTime = new DateTimeOffset(); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); Configuration.Current.UseCommandHandler <NonEventSourcedCommandTarget, TestCommand>(async(_, cmd) => { if (cmd.ETag == "first") { await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = true }); } else { deliveredTime = Clock.Now(); } }); // act await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = true, ETag = "first" }, dueTime : DateTimeOffset.Parse("2016-02-13 01:05:00 AM")); await AdvanceClock(clockName : clockName, by : 1.Hours()); // assert deliveredTime.Should().Be(DateTimeOffset.Parse("2016-02-13 01:05:00 AM")); }
public async Task When_a_scheduled_command_fails_and_the_clock_is_advanced_again_then_it_can_be_retried() { // arrange var target = new NonEventSourcedCommandTarget { IsValid = false }; await Save(target); await Schedule( target.Id, new TestCommand(), Clock.Now().AddDays(10)); // act await AdvanceClock(TimeSpan.FromDays(10.1)); target.CommandsFailed .Should() .HaveCount(1); target .CommandsEnacted .Should() .HaveCount(0); target.IsValid = true; await AdvanceClock(TimeSpan.FromHours(1)); target .CommandsFailed .Should() .HaveCount(1); target .CommandsEnacted .Should() .HaveCount(1); }
public override async Task A_command_handler_can_request_retry_of_a_failed_command_as_late_as_it_wants() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { OnHandleScheduledCommandError = async(commandTarget, failed) => failed.Retry(after: 1.Hours()) }; await Save(target); // act await Schedule(target.Id, new TestCommand(isValid : false), Clock.Now().Add(2.Minutes())); await AdvanceClock(5.Minutes()); await AdvanceClock(5.Minutes()); // should not trigger a retry //assert target = await Get <NonEventSourcedCommandTarget>(target.Id); target.CommandsFailed.Should().HaveCount(1); }
public async Task When_a_command_fails_and_is_scheduled_for_retry_then_advancing_the_virtual_clock_triggers_redelivery() { VirtualClock.Start(); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { IsValid = false }; var retries = 0; var configuration = Configuration.Current; await configuration.Store <NonEventSourcedCommandTarget>().Put(target); configuration.UseCommandHandler <NonEventSourcedCommandTarget, TestCommand>( enactCommand: async(_, __) => { }, handleScheduledCommandException: async(_, command) => { if (command.NumberOfPreviousAttempts >= 12) { command.Cancel(); return; } retries++; command.Retry(1.Hours()); }); var scheduler = configuration.CommandScheduler <NonEventSourcedCommandTarget>(); await scheduler.Schedule(target.Id, new TestCommand(), dueTime : Clock.Now().AddHours(1)); VirtualClock.Current.AdvanceBy(1.Days()); retries.Should().Be(12); }
public override async Task Immediately_scheduled_commands_triggered_by_a_scheduled_command_have_their_due_time_set_to_the_causative_command_clock() { // arrange var deliveredTime = new DateTimeOffset(); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); Configuration.Current.UseCommandHandler<NonEventSourcedCommandTarget, TestCommand>(async (_, cmd) => { if (cmd.ETag == "first") { await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = true }); } else { deliveredTime = Clock.Now(); } }); // act await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = true, ETag = "first" }, dueTime: DateTimeOffset.Parse("2016-02-13 01:05:00 AM")); await AdvanceClock(clockName: clockName, by: 1.Hours()); // assert deliveredTime.Should().Be(DateTimeOffset.Parse("2016-02-13 01:05:00 AM")); }
public override async Task A_command_handler_can_request_retry_of_a_failed_command_as_late_as_it_wants() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { OnHandleScheduledCommandError = async (commandTarget, failed) => failed.Retry(after: 1.Hours()) }; await Save(target); // act await Schedule(target.Id, new TestCommand(isValid: false), Clock.Now().Add(2.Minutes())); await AdvanceClock(5.Minutes()); await AdvanceClock(5.Minutes()); // should not trigger a retry //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsFailed.Should().HaveCount(1); }
public async Task when_a_command_is_applied_directly_the_command_is_executed() { var target = new NonEventSourcedCommandTarget(); await target.ApplyAsync(new TestCommand()); target.CommandsEnacted.Should().HaveCount(1); }
private static NonEventSourcedCommandTarget CreateCommandTarget() { var target = new NonEventSourcedCommandTarget(Any.Word()); Save(target).Wait(); return target; }
public override async Task A_command_handler_can_cancel_a_scheduled_command_after_it_fails() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()) { OnHandleScheduledCommandError = async (commandTarget, failed) => failed.Cancel() }; await Save(target); // act await Schedule(target.Id, new TestCommand(isValid: false), Clock.Now().AddMinutes(2)); await AdvanceClock(5.Minutes()); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsFailed.Should().HaveCount(1); }
public override async Task When_a_command_is_scheduled_but_an_exception_is_thrown_in_a_handler_then_an_error_is_recorded() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand(isValid: false)); //assert using (var db = CommandSchedulerDbContext()) { var aggregateId = target.Id.ToGuidV3(); var error = db.Errors.Single(e => e.ScheduledCommand.AggregateId == aggregateId); error.Error.Should().Contain("CommandValidationException"); } }
public override async Task When_command_is_durable_but_immediate_delivery_succeeds_then_it_is_not_redelivered() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); // act await Schedule(target.Id, new TestCommand { RequiresDurableScheduling = true }); await AdvanceClock(2.Days()); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task Scheduled_commands_are_delivered_immediately_if_past_due_per_the_scheduler_clock() { // arrange var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); var schedulerClockTime = DateTimeOffset.Parse("2016-02-13 03:03:48 PM"); // act await Schedule(target.Id, new TestCommand(), schedulerClockTime.AddMinutes(-2)); //assert target = await Get<NonEventSourcedCommandTarget>(target.Id); target.CommandsEnacted.Should().HaveCount(1); }
public override async Task Scheduled_commands_with_no_due_time_are_delivered_at_Clock_Now_when_delivery_is_deferred() { // arrange var deliveredTime = new DateTimeOffset(); var target = new NonEventSourcedCommandTarget(Any.CamelCaseName()); await Save(target); Configuration .Current .UseCommandHandler<NonEventSourcedCommandTarget, TestCommand>(async (_, __) => deliveredTime = Clock.Now()); // act await Schedule(target.Id, new TestCommand { CanBeDeliveredDuringScheduling = false }, dueTime: null); await AdvanceClock( clockName: clockName, by: 1.Hours()); // assert deliveredTime .Should() .Be(Clock.Now()); }