public async Task Trigger( ScheduledCommand scheduled, SchedulerAdvancedResult result, CommandSchedulerDbContext db) { await deliver(scheduled, result, db); }
internal async Task Trigger( ScheduledCommand scheduled, SchedulerAdvancedResult result, CommandSchedulerDbContext db) { var deliver = commandDispatchers.IfContains(scheduled.AggregateType) .ElseDefault(); if (deliver == null) { // QUESTION: (Trigger) is this worth raising a warning for or is there a reasonable chance that not registering a handler was deliberate? // var error = ScheduledCommandFailure(); // // activity.OnNext(new CommandSchedulerActivity(scheduled, error)); // // result.Add(error); // db.Errors.Add(error); } else { await deliver(scheduled); result.Add(scheduled.Result); } scheduled.Attempts++; await db.SaveChangesAsync(); }
private async Task <SchedulerAdvancedResult> Advance(string clockName, DateTimeOffset?to = null, TimeSpan?by = null, Func <IQueryable <ScheduledCommand>, IQueryable <ScheduledCommand> > query = null) { if (clockName == null) { throw new ArgumentNullException("clockName"); } if (to == null && @by == null) { throw new ArgumentException("Either to or by must be specified."); } using (var db = createCommandSchedulerDbContext()) { var clock = await db.Clocks.SingleOrDefaultAsync(c => c.Name == clockName); if (clock == null) { throw new ObjectNotFoundException(string.Format("No clock named {0} was found.", clockName)); } to = to ?? clock.UtcNow.Add(@by.Value); if (to < clock.UtcNow) { throw new InvalidOperationException(string.Format("A clock cannot be moved backward. ({0})", new { Clock = clock.ToJson(), RequestedTime = to })); } var result = new SchedulerAdvancedResult(to.Value); clock.UtcNow = to.Value; await db.SaveChangesAsync(); var commands = db.ScheduledCommands .Due(asOf: to) .Where(c => c.Clock.Id == clock.Id); if (query != null) { commands = query(commands); } // ToArray closes the connection so that when we perform saves during the loop there are no connection errors foreach (var scheduled in await commands.ToArrayAsync()) { //clock.UtcNow = scheduled.DueTime ?? to.Value; await Trigger(scheduled, result, db); } return(result); } }
private async Task<SchedulerAdvancedResult> Advance( string clockName, DateTimeOffset? to = null, TimeSpan? by = null, Func<IQueryable<ScheduledCommand>, IQueryable<ScheduledCommand>> query = null) { if (clockName == null) { throw new ArgumentNullException(nameof(clockName)); } if (to == null && by == null) { throw new ArgumentException($"Either {nameof(to)} or {nameof(by)} must be specified."); } using (var db = createCommandSchedulerDbContext()) { var clock = await db.Clocks.SingleOrDefaultAsync(c => c.Name == clockName); if (clock == null) { throw new ObjectNotFoundException($"No clock named {clockName} was found."); } to = to ?? clock.UtcNow.Add(by.Value); if (to < clock.UtcNow) { throw new InvalidOperationException($"A clock cannot be moved backward. ({new { Clock = clock.ToJson(), RequestedTime = to }})"); } var result = new SchedulerAdvancedResult(to.Value); clock.UtcNow = to.Value; await db.SaveChangesAsync(); var commands = db.ScheduledCommands .Due(asOf: to) .Where(c => c.Clock.Id == clock.Id); if (query != null) { commands = query(commands); } // ToArray closes the connection so that when we perform saves during the loop there are no connection errors foreach (var scheduled in await commands.ToArrayAsync()) { await Configuration.Current.DeserializeAndDeliver(scheduled, db); result.Add(scheduled.Result); } return result; } }
/// <summary> /// Triggers all commands matched by the specified query. /// </summary> /// <param name="query">The query.</param> /// <returns> /// A result summarizing the triggered commands. /// </returns> /// <exception cref="System.ArgumentNullException">query</exception> /// <remarks>If the query matches commands that have been successfully applied already or abandoned, they will be re-applied.</remarks> public async Task<SchedulerAdvancedResult> Trigger(Func<IQueryable<ScheduledCommand>, IQueryable<ScheduledCommand>> query) { // QUESTION: (Trigger) re: the remarks XML comment, would it be clearer to have two methods, e.g. something like TriggerAnyCommands and TriggerEligibleCommands? if (query == null) { throw new ArgumentNullException(nameof(query)); } var result = new SchedulerAdvancedResult(); using (var db = createCommandSchedulerDbContext()) { var commands = query(db.ScheduledCommands).ToArray(); foreach (var scheduled in commands) { await Trigger(scheduled, result, db); } } return result; }
private async Task<SchedulerAdvancedResult> Advance(string clockName, DateTimeOffset? to = null, TimeSpan? by = null, Func<IQueryable<ScheduledCommand>, IQueryable<ScheduledCommand>> query = null) { if (clockName == null) { throw new ArgumentNullException(nameof(clockName)); } if (to == null && @by == null) { throw new ArgumentException($"Either {nameof(to)} or {nameof(by)} must be specified."); } using (var db = createCommandSchedulerDbContext()) { var clock = await db.Clocks.SingleOrDefaultAsync(c => c.Name == clockName); if (clock == null) { throw new ObjectNotFoundException($"No clock named {clockName} was found."); } to = to ?? clock.UtcNow.Add(@by.Value); if (to < clock.UtcNow) { throw new InvalidOperationException($"A clock cannot be moved backward. ({new { Clock = clock.ToJson(), RequestedTime = to }})"); } var result = new SchedulerAdvancedResult(to.Value); clock.UtcNow = to.Value; await db.SaveChangesAsync(); var commands = db.ScheduledCommands .Due(asOf: to) .Where(c => c.Clock.Id == clock.Id); if (query != null) { commands = query(commands); } // ToArray closes the connection so that when we perform saves during the loop there are no connection errors foreach (var scheduled in await commands.ToArrayAsync()) { await Trigger(scheduled, result, db); } return result; } }
public async Task Trigger( ScheduledCommand scheduled, SchedulerAdvancedResult result, CommandSchedulerDbContext db) => await deliver(scheduled, result, db);
public override async Task When_triggering_specific_commands_then_the_result_can_be_used_to_evaluate_failures() { // arrange var target = new CommandTarget(Any.CamelCaseName()); await store.Put(target); var schedulerAdvancedResult = new SchedulerAdvancedResult(); // act await scheduler.Schedule(target.Id, new TestCommand(isValid: false), Clock.Now().AddDays(2)); using (var db = Configuration.Current.CommandSchedulerDbContext()) { var aggregateId = target.Id.ToGuidV3(); var command = db.ScheduledCommands .Single(c => c.AggregateId == aggregateId); await Configuration.Current .SchedulerClockTrigger() .Trigger(command, schedulerAdvancedResult, db); } //assert schedulerAdvancedResult .FailedCommands .Should() .HaveCount(1); }
public async Task Trigger(ScheduledCommand scheduled, SchedulerAdvancedResult result, CommandSchedulerDbContext db) { await ClockTrigger.Trigger(scheduled, result, db); }