public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags() { var senderId = Any.Word(); await store.Put(new CommandTarget(senderId)); var targetIds = new[] { Any.Word(), Any.Word(), Any.Word() }; var results = new ConcurrentBag <RequestReply>(); configuration.TraceScheduledCommands( onScheduling: cmd => { var requestReply = ((dynamic)cmd).Command as RequestReply; if (requestReply != null) { results.Add(requestReply); } }); var initialEtag = "initial".ToETag(); var firstCommand = new SendRequests(targetIds) { ETag = initialEtag }; var scheduledCommand = new ScheduledCommand <CommandTarget>( firstCommand, senderId); await scheduler.Deliver(scheduledCommand); var secondCommand = new SendRequests(targetIds) { ETag = initialEtag }; scheduledCommand = new ScheduledCommand <CommandTarget>( secondCommand, senderId); // redeliver await scheduler.Deliver(scheduledCommand); Console.WriteLine(results.ToJson()); results.Should().HaveCount(6); results.Select(r => r.ETag) .Distinct() .Should() .HaveCount(3); }
internal static ICommandScheduler <TAggregate> Wrap <TAggregate>( this ICommandScheduler <TAggregate> scheduler, ScheduledCommandInterceptor <TAggregate> schedule = null, ScheduledCommandInterceptor <TAggregate> deliver = null) { schedule = schedule ?? (async(c, next) => await next(c)); deliver = deliver ?? (async(c, next) => await next(c)); return(Create <TAggregate>( async command => await schedule(command, async c => await scheduler.Schedule(c)), async command => await deliver(command, async c => await scheduler.Deliver(c)))); }
internal static async Task DeserializeAndDeliverScheduledCommand <TAggregate>( ScheduledCommand scheduled, ICommandScheduler <TAggregate> scheduler) { try { var command = scheduled.ToScheduledCommand <TAggregate>(); await scheduler.Deliver(command); scheduled.Result = command.Result; } catch (Exception exception) { scheduled.Result = new CommandFailed(scheduled, exception); } }
internal static void DeliverIfPreconditionIsSatisfiedWithin <TAggregate>( this ICommandScheduler <TAggregate> scheduler, TimeSpan timespan, IScheduledCommand <TAggregate> scheduledCommand, IEventBus eventBus) where TAggregate : IEventSourced { eventBus.Events <IEvent>() .Where( e => e.AggregateId == scheduledCommand.DeliveryPrecondition.AggregateId && e.ETag == scheduledCommand.DeliveryPrecondition.ETag) .Take(1) .Timeout(timespan) .Subscribe( e => { Task.Run(() => scheduler.Deliver(scheduledCommand)).Wait(); }, onError: ex => { eventBus.PublishErrorAsync(new EventHandlingError(ex, scheduler)); }); }
public static async Task DeserializeAndDeliverScheduledCommand <TAggregate>( ScheduledCommand scheduled, ICommandScheduler <TAggregate> scheduler) where TAggregate : IEventSourced { var command = scheduled.ToScheduledCommand <TAggregate>(); //here we are setting the command.SequenceNumber to the scheduled.SequenceNumber because when //multiple commands are scheduled simultaniously against the same aggregate we were decrementing the //scheduled.SequenceNumber correctly, however we were not updating the command.SequenceNumber. //this is to prevent any side effects that may have been caused by that bug command.SequenceNumber = scheduled.SequenceNumber; await scheduler.Deliver(command); scheduled.Result = command.Result; }