/// <summary> /// Allows awaiting delivery of all commands that are currently due on the command scheduler. /// </summary> /// <param name="scheduler">The command scheduler.</param> /// <param name="clockName">The name of the clock on which the commands are scheduled.</param> /// <returns></returns> public static async Task Done(this SqlCommandScheduler scheduler, string clockName = null) { clockName = clockName ?? SqlCommandScheduler.DefaultClockName; Debug.WriteLine(string.Format("SqlCommandScheduler: Waiting for clock {0}", clockName)); for (var i = 0; i < 10; i++) { using (var db = scheduler.CreateCommandSchedulerDbContext()) { var due = db.ScheduledCommands .Due() .Where(c => c.Clock.Name == clockName); if (!await due.AnyAsync()) { return; } var commands = await due.ToArrayAsync(); Debug.WriteLine(string.Format("SqlCommandScheduler: Triggering {0} commands", commands.Count())); foreach (var scheduledCommand in commands) { Debug.WriteLine(string.Format("SqlCommandScheduler: Triggering {0}:{1}", scheduledCommand.AggregateId, scheduledCommand.SequenceNumber)); await scheduler.Trigger(scheduledCommand, new SchedulerAdvancedResult(), db); } await Task.Delay(400); } } Debug.WriteLine(string.Format("SqlCommandScheduler: Done waiting for clock {0}", clockName)); }
/// <summary> /// Raises an event that occurs when a message has been brokered. /// </summary> /// <returns> /// The task object representing the asynchronous operation. /// </returns> /// <param name="session">The message session.</param> /// <param name="message">The brokered message.</param> public async Task OnMessageAsync(MessageSession session, BrokeredMessage message) { var json = message.GetBody <string>(); var @event = json.FromJsonTo <ServiceBusScheduledCommand>(); @event.BrokeredMessage = message; onMessage(@event); var result = await scheduler.Trigger(commands => commands.Due(@event.DueTime) .Where(c => c.AggregateId == @event.AggregateId)); if (!result.FailedCommands.Any()) { if (result.SuccessfulCommands.Any()) { Debug.WriteLine("ServiceBusCommandQueueReceiver: completing on success: " + @event.AggregateId); await message.CompleteAsync(); return; } using (var db = scheduler.CreateCommandSchedulerDbContext()) { // if the command was already applied, we can complete the message. its job is done. if (db.ScheduledCommands .Where(cmd => cmd.AppliedTime != null || cmd.FinalAttemptTime != null) .Where(cmd => cmd.SequenceNumber == @event.SequenceNumber) .Any(cmd => cmd.AggregateId == @event.AggregateId)) { Debug.WriteLine("ServiceBusCommandQueueReceiver: completing because command was previously applied: " + @event.AggregateId); await message.CompleteAsync(); } } } }