private async Task <string> ClockNameForEvent(
            IScheduledCommand <TAggregate> scheduledCommandEvent,
            CommandSchedulerDbContext db)
        {
            // TODO: (ClockNameForEvent) clean this up
            var clockName =
                scheduledCommandEvent.IfTypeIs <IHaveExtensibleMetada>()
                .Then(e => ((object)e.Metadata)
                      .IfTypeIs <IDictionary <string, object> >()
                      .Then(m => m.IfContains("ClockName")
                            .Then(v => v.ToString())))
                .ElseDefault();

            if (clockName == null)
            {
                clockName = GetClockName(scheduledCommandEvent);

                if (clockName == null)
                {
                    var lookupValue = GetClockLookupKey(scheduledCommandEvent);
                    clockName = (await db.ClockMappings
                                 .Include(m => m.Clock)
                                 .SingleOrDefaultAsync(c => c.Value == lookupValue))
                                .IfNotNull()
                                .Then(c => c.Clock.Name)
                                .Else(() => SqlCommandScheduler.DefaultClockName);
                }
            }

            return(clockName);
        }
Esempio n. 2
0
        public async Task Schedule(IScheduledCommand <TAggregate> scheduledCommand)
        {
            var storedScheduledCommand = await Storage.StoreScheduledCommand(
                scheduledCommand,
                createCommandSchedulerDbContext,
                (scheduledCommandEvent1, db) => ClockNameForEvent(this, scheduledCommandEvent1, db));

            Activity.OnNext(new CommandScheduled(scheduledCommand)
            {
                ClockName = storedScheduledCommand.Clock.Name
            });

            // deliver the command immediately if appropriate
            if (scheduledCommand.IsDue(storedScheduledCommand.Clock))
            {
                // sometimes the command depends on a precondition event that hasn't been saved
                if (!await commandPreconditionVerifier.IsPreconditionSatisfied(scheduledCommand))
                {
                    this.DeliverIfPreconditionIsSatisfiedWithin(
                        TimeSpan.FromSeconds(10),
                        scheduledCommand,
                        eventBus);
                }
                else
                {
                    var scheduler = Configuration.Current.CommandScheduler <TAggregate>();
                    await scheduler.Deliver(scheduledCommand);
                }
            }
        }
Esempio n. 3
0
        private async Task Deliver <TAggregate>(
            IScheduledCommand <TAggregate> cmd,
            Func <IScheduledCommand <TAggregate>, Task> next)
            where TAggregate : class
        {
            IClock clock;

            if (cmd.DueTime != null)
            {
                clock = Domain.Clock.Create(() => cmd.DueTime.Value);
            }
            else
            {
                clock = cmd.Clock;
            }

            using (CommandContext.Establish(cmd.Command, clock))
            {
                await next(cmd);

                if (!cmd.Command.RequiresDurableScheduling())
                {
                    return;
                }

                await Storage.UpdateScheduledCommand(
                    cmd,
                    createDbContext);
            }
        }
Esempio n. 4
0
        private async Task Deliver(IScheduledCommand <TAggregate> scheduledCommand, bool durable)
        {
            IClock clock = null;

            if (scheduledCommand.DueTime != null)
            {
                clock = Domain.Clock.Create(() => scheduledCommand.DueTime.Value);
            }

            using (CommandContext.Establish(scheduledCommand.Command, clock))
            {
                var repository = getRepository();

                await repository.ApplyScheduledCommand(scheduledCommand,
                                                       commandPreconditionVerifier);

                Activity.OnNext(scheduledCommand.Result);

                if (!durable)
                {
                    return;
                }

                await Storage.UpdateScheduledCommand(
                    scheduledCommand,
                    createCommandSchedulerDbContext);
            }
        }
        /// <summary>
        /// Schedules the specified command.
        /// </summary>
        /// <param name="scheduledCommand">The scheduled command.</param>
        /// <returns>
        /// A task that is complete when the command has been successfully scheduled.
        /// </returns>
        /// <exception cref="System.NotSupportedException">Non-immediate scheduling is not supported.</exception>
        public virtual async Task Schedule(IScheduledCommand <TAggregate> scheduledCommand)
        {
            if (scheduledCommand.Result is CommandDeduplicated)
            {
                return;
            }

            if (scheduledCommand.Command.CanBeDeliveredDuringScheduling() && scheduledCommand.IsDue())
            {
                if (!await PreconditionHasBeenMet(scheduledCommand))
                {
                    CommandScheduler.DeliverIfPreconditionIsMetSoon(
                        scheduledCommand,
                        Configuration.Current);
                }
                else
                {
                    // resolve the command scheduler so that delivery goes through the whole pipeline
                    await Configuration.Current.CommandScheduler <TAggregate>().Deliver(scheduledCommand);

                    return;
                }
            }

            if (scheduledCommand.Result == null)
            {
                throw new NotSupportedException("Deferred scheduling is not supported by the current command scheduler pipeline configuration.");
            }
        }
 public async Task Deliver(IScheduledCommand <TAggregate> scheduledCommand)
 {
     using (CommandContext.Establish(scheduledCommand.Command))
     {
         await repository.ApplyScheduledCommand(scheduledCommand);
     }
 }
Esempio n. 7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CommandFailed{TCommand}"/> class.
 /// </summary>
 /// <param name="command">The command.</param>
 /// <param name="scheduledCommand">The scheduled command.</param>
 /// <param name="exception">The exception.</param>
 internal CommandFailed(
     TCommand command,
     IScheduledCommand scheduledCommand,
     Exception exception) : base(scheduledCommand, exception)
 {
     Command = command;
 }
Esempio n. 8
0
        internal static void DeliverIfPreconditionIsMetSoon <TAggregate>(
            IScheduledCommand <TAggregate> scheduledCommand,
            Configuration configuration,
            int timeoutInMilliseconds = 10000)
            where TAggregate : class
        {
            Guid aggregateId;

            if (Guid.TryParse(scheduledCommand.DeliveryPrecondition.Scope, out aggregateId))
            {
                var eventBus = configuration.EventBus;

                var timeout = TimeSpan.FromMilliseconds(timeoutInMilliseconds);

                eventBus.Events <IEvent>()
                .Where(
                    e => e.AggregateId == aggregateId &&
                    e.ETag == scheduledCommand.DeliveryPrecondition.ETag)
                .Take(1)
                .Timeout(timeout)
                .Subscribe(
                    e => Task.Run(() => DeliverImmediatelyOnConfiguredScheduler(scheduledCommand, configuration)).Wait(),
                    onError: ex => eventBus.PublishErrorAsync(new EventHandlingError(ex)));
            }
        }
        public async Task Schedule(IScheduledCommand <TAggregate> scheduledCommandEvent)
        {
            Debug.WriteLine("SqlCommandScheduler.Schedule: " + Description(scheduledCommandEvent));

            var storedScheduledCommand = await StoreScheduledCommand(scheduledCommandEvent);

            var scheduledCommand = storedScheduledCommand.ToScheduledCommand <TAggregate>();

            Activity.OnNext(new CommandScheduled(scheduledCommand)
            {
                ClockName = storedScheduledCommand.Clock.Name
            });

            // deliver the command immediately if appropriate
            if (storedScheduledCommand.ShouldBeDeliveredImmediately())
            {
                // sometimes the command depends on a precondition event that hasn't been saved
                if (!await commandPreconditionVerifier.VerifyPrecondition(scheduledCommand))
                {
                    this.DeliverIfPreconditionIsSatisfiedWithin(
                        TimeSpan.FromSeconds(10),
                        scheduledCommand,
                        eventBus);
                }
                else
                {
                    await Deliver(scheduledCommand,
                                  durable : !storedScheduledCommand.NonDurable);
                }
            }
        }
        /// <summary>
        /// Schedules the specified command.
        /// </summary>
        /// <param name="scheduledCommand">The scheduled command.</param>
        /// <returns>A task that is complete when the command has been successfully scheduled.</returns>
        public async Task Schedule(IScheduledCommand <TAggregate> scheduledCommand)
        {
            var dueTime = scheduledCommand.DueTime;

            var domainNow = Clock.Current.Now();

            if (dueTime == null || dueTime <= domainNow)
            {
                Debug.WriteLine(string.Format("Schedule (applying {1} immediately): @ {0}", domainNow, scheduledCommand.Command.CommandName));

                // schedule immediately
                await Deliver(scheduledCommand);

                return;
            }

            // schedule for later
            VirtualClock.Schedule(scheduledCommand,
                                  dueTime.Value,
                                  (s, command) =>
            {
                try
                {
                    Deliver(command).Wait();
                }
                catch (Exception exception)
                {
                    Console.WriteLine("InMemoryCommandScheduler caught:\n" + exception);
                }

                return(Disposable.Empty);
            });
        }
Esempio n. 11
0
 private static Clock TryToGetSqlClockToScheduleOn <TAggregate>(
     IScheduledCommand <TAggregate> scheduledCommand) where TAggregate : class =>
 scheduledCommand.Clock as Clock ??
 scheduledCommand.Clock
 .IfTypeIs <AnonymousClock>()
 .Then(c => c.ParentClock as Clock)
 .ElseDefault();
Esempio n. 12
0
        private static async Task SaveScheduledCommandToDatabase <TAggregate>(
            CommandSchedulerDbContext db,
            ScheduledCommand storedScheduledCommand,
            IScheduledCommand <TAggregate> scheduledCommand)
        {
            var etag = new ETag
            {
                Scope             = scheduledCommand.TargetId,
                ETagValue         = scheduledCommand.Command.ETag,
                CreatedDomainTime = Domain.Clock.Now(),
                CreatedRealTime   = DateTimeOffset.UtcNow
            };

            while (true)
            {
                try
                {
                    await InsertScheduledCommandAndETag(db, storedScheduledCommand, etag);

                    break;
                }
                catch (Exception exception)
                {
                    if (!exception.IsConcurrencyException())
                    {
                        throw;
                    }

                    if (exception.ToString().Contains(@"object 'Scheduler.ScheduledCommand'"))
                    {
                        if (storedScheduledCommand.SequenceNumber < 0)
                        {
                            // for scheduler-assigned sequence numbers, decrement and retry
                            storedScheduledCommand.SequenceNumber--;
                        }
                        else
                        {
                            // this is not a scheduler-assigned sequence number
                            break;
                        }
                    }
                    else if (exception.ToString().Contains(@"object 'Scheduler.ETag'"))
                    {
                        scheduledCommand.Result = new CommandDeduplicated(
                            scheduledCommand,
                            "Schedule");
                        return;
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            scheduledCommand.Result = new CommandScheduled(
                scheduledCommand,
                storedScheduledCommand.Clock);
        }
Esempio n. 13
0
        private static async Task FailScheduledCommand <TAggregate>(
            IEventSourcedRepository <TAggregate> repository,
            IScheduledCommand <TAggregate> scheduled,
            Exception exception  = null,
            TAggregate aggregate = null)
            where TAggregate : class, IEventSourced
        {
            var failure = (CommandFailed)createMethod
                          .MakeGenericMethod(scheduled.Command.GetType())
                          .Invoke(null, new object[] { scheduled.Command, scheduled, exception });

            var previousAttempts = scheduled.IfHas <int>(s => s.Metadata.NumberOfPreviousAttempts)
                                   .ElseDefault();

            failure.NumberOfPreviousAttempts = previousAttempts;

            if (aggregate != null)
            {
                // TODO: (FailScheduledCommand) refactor so that getting hold of the handler is simpler
                var scheduledCommandOfT = scheduled.Command as Command <TAggregate>;
                if (scheduledCommandOfT != null)
                {
                    if (scheduledCommandOfT.Handler != null)
                    {
                        await scheduledCommandOfT.Handler
                        .HandleScheduledCommandException((dynamic)aggregate,
                                                         (dynamic)failure);
                    }
                }

                if (!(exception is ConcurrencyException))
                {
                    try
                    {
                        await repository.Save(aggregate);
                    }
                    catch (Exception ex)
                    {
                        // TODO: (FailScheduledCommand) surface this more clearly
                        Trace.Write(ex);
                    }
                }
                else if (scheduled.Command is ConstructorCommand <TAggregate> )
                {
                    failure.Cancel();
                    scheduled.Result = failure;
                    return;
                }
            }

            if (!failure.IsCanceled &&
                failure.RetryAfter == null &&
                failure.NumberOfPreviousAttempts < DefaultNumberOfRetriesOnException)
            {
                failure.Retry(TimeSpan.FromMinutes(Math.Pow(failure.NumberOfPreviousAttempts + 1, 2)));
            }

            scheduled.Result = failure;
        }
Esempio n. 14
0
 public CommandScheduled(IScheduledCommand scheduledCommand)
 {
     if (scheduledCommand == null)
     {
         throw new ArgumentNullException("scheduledCommand");
     }
     this.scheduledCommand = scheduledCommand;
 }
 protected ScheduledCommandResult(IScheduledCommand command)
 {
     if (command == null)
     {
         throw new ArgumentNullException(nameof(command));
     }
     this.command = command;
 }
Esempio n. 16
0
 internal static async Task DeliverImmediatelyOnConfiguredScheduler <TAggregate>(
     IScheduledCommand <TAggregate> command,
     Configuration configuration)
     where TAggregate : class, IEventSourced
 {
     var scheduler = configuration.CommandScheduler <TAggregate>();
     await scheduler.Deliver(command);
 }
Esempio n. 17
0
 internal static CommandFailed Create <TCommand>(
     TCommand command,
     IScheduledCommand scheduledCommand,
     Exception exception)
     where TCommand : class, ICommand
 {
     return(new CommandFailed <TCommand>(command, scheduledCommand, exception));
 }
Esempio n. 18
0
 public CommandScheduled(IScheduledCommand scheduledCommand)
 {
     if (scheduledCommand == null)
     {
         throw new ArgumentNullException("scheduledCommand");
     }
     this.scheduledCommand = scheduledCommand;
 }
Esempio n. 19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ScheduledCommandResult"/> class.
 /// </summary>
 /// <param name="command">The command.</param>
 /// <exception cref="System.ArgumentNullException"></exception>
 protected ScheduledCommandResult(IScheduledCommand command)
 {
     if (command == null)
     {
         throw new ArgumentNullException(nameof(command));
     }
     this.command = command;
 }
Esempio n. 20
0
            public void Add(IScheduledCommand command)
            {
                var now = Clock.Now();

                commands.AddOrUpdate(
                    command,
                    now,
                    (c, t) => now);
            }
        public async Task <bool> IsPreconditionSatisfied(IScheduledCommand scheduledCommand)
        {
            if (scheduledCommand.DeliveryPrecondition == null)
            {
                return(true);
            }

            throw new InvalidOperationException("No ICommandPreconditionVerifier has been configured.");
        }
        public async Task<bool> IsPreconditionSatisfied(IScheduledCommand scheduledCommand)
        {
            if (scheduledCommand.DeliveryPrecondition == null)
            {
                return true;
            }

            throw new InvalidOperationException("No ICommandPreconditionVerifier has been configured.");
        }
Esempio n. 23
0
        /// <summary>
        /// Delivers the specified scheduled command to the target.
        /// </summary>
        /// <param name="scheduledCommand">The scheduled command to be applied to the target.</param>
        /// <returns>
        /// A task that is complete when the command has been applied.
        /// </returns>
        /// <remarks>
        /// The scheduler will apply the command and save it, potentially triggering additional consequences.
        /// </remarks>
        public virtual async Task Deliver(IScheduledCommand <TAggregate> scheduledCommand)
        {
            if (scheduledCommand.Result is CommandDelivered)
            {
                return;
            }

            await store.ApplyScheduledCommand(scheduledCommand, etagChecker);
        }
Esempio n. 24
0
        internal static async Task UpdateScheduledCommand <TAggregate>(
            IScheduledCommand <TAggregate> scheduledCommand,
            Func <CommandSchedulerDbContext> createDbContext) where TAggregate : class, IEventSourced
        {
            using (var db = createDbContext())
            {
                var storedCommand = await db.ScheduledCommands
                                    .SingleOrDefaultAsync(c => c.AggregateId == scheduledCommand.AggregateId &&
                                                          c.SequenceNumber == scheduledCommand.SequenceNumber);

                if (storedCommand == null)
                {
                    if (!scheduledCommand.Command.RequiresDurableScheduling)
                    {
                        return;
                    }

                    throw new InvalidOperationException("Scheduled command not found");
                }

                storedCommand.Attempts++;

                var result = scheduledCommand.Result;

                if (result is CommandSucceeded)
                {
                    storedCommand.AppliedTime = Domain.Clock.Now();
                }
                else
                {
                    var failure = (CommandFailed)result;

                    // reschedule as appropriate
                    var now = Domain.Clock.Now();
                    if (failure.IsCanceled || failure.RetryAfter == null)
                    {
                        // no further retries
                        storedCommand.FinalAttemptTime = now;
                    }
                    else
                    {
                        storedCommand.DueTime = now + failure.RetryAfter;
                    }

                    db.Errors.Add(new CommandExecutionError
                    {
                        ScheduledCommand = storedCommand,
                        Error            = result.IfTypeIs <CommandFailed>()
                                           .Then(f => f.Exception.ToJson())
                                           .ElseDefault()
                    });
                }

                await db.SaveChangesAsync();
            }
        }
Esempio n. 25
0
        private static ScheduledCommandResult FailScheduledCommand <TAggregate>(
            IEventSourcedRepository <TAggregate> repository,
            IScheduledCommand <TAggregate> scheduled,
            Exception exception  = null,
            TAggregate aggregate = null)
            where TAggregate : class, IEventSourced
        {
            var failure = (CommandFailed)createMethod
                          .MakeGenericMethod(scheduled.Command.GetType())
                          .Invoke(null, new object[] { scheduled.Command, scheduled, exception });

            var previousAttempts = scheduled.IfHas <int>(s => s.Metadata.NumberOfPreviousAttempts)
                                   .ElseDefault();

            failure.NumberOfPreviousAttempts = previousAttempts;

            if (aggregate != null)
            {
                // TODO: (FailScheduledCommand) refactor so that getting hold of the handler is simpler
                scheduled.Command
                .IfTypeIs <Command <TAggregate> >()
                .ThenDo(c =>
                {
                    if (c.Handler != null)
                    {
                        Task task = c.Handler
                                    .HandleScheduledCommandException((dynamic)aggregate,
                                                                     (dynamic)failure);
                        task.Wait();
                    }
                });

                if (!(exception is ConcurrencyException))
                {
                    try
                    {
                        repository.Save(aggregate);
                    }
                    catch (Exception ex)
                    {
                        // TODO: (FailScheduledCommand) surface this more clearly
                        Trace.Write(ex);
                    }
                }
            }
            else
            {
                if (failure.NumberOfPreviousAttempts < 5)
                {
                    failure.Retry(TimeSpan.FromMinutes(failure.NumberOfPreviousAttempts + 1));
                }
            }

            return(failure);
        }
Esempio n. 26
0
        /// <summary>
        /// Delivers the specified scheduled command to the target.
        /// </summary>
        /// <param name="scheduledCommand">The scheduled command to be applied to the target.</param>
        /// <returns>
        /// A task that is complete when the command has been applied.
        /// </returns>
        /// <remarks>
        /// The scheduler will apply the command and save it, potentially triggering additional consequences.
        /// </remarks>
        public async Task Deliver(IScheduledCommand <TAggregate> scheduledCommand)
        {
            if (scheduledCommand.Result is CommandDelivered)
            {
                return;
            }

            var store = getStore();

            await ApplyScheduledCommand(store, scheduledCommand);
        }
Esempio n. 27
0
        private async Task Schedule <TAggregate>(
            IScheduledCommand <TAggregate> cmd,
            Func <IScheduledCommand <TAggregate>, Task> next)
            where TAggregate : class
        {
            await Storage.StoreScheduledCommand(
                cmd,
                createDbContext,
                GetClockName);

            await next(cmd);
        }
Esempio n. 28
0
        internal static IDisposable Schedule <TAggregate>(
            IScheduledCommand <TAggregate> scheduledCommand,
            DateTimeOffset dueTime,
            Func <IScheduler, IScheduledCommand <TAggregate>, IDisposable> func)
        {
            var scheduler = Clock.Current
                            .IfTypeIs <VirtualClock>()
                            .Then(c => (IScheduler)c.Scheduler)
                            .Else(() => CurrentThreadScheduler.Instance);

            return(scheduler.Schedule(scheduledCommand, dueTime, func));
        }
Esempio n. 29
0
        internal static IDisposable Schedule <TAggregate>(
            IScheduledCommand <TAggregate> scheduledCommand,
            DateTimeOffset dueTime,
            Func <IScheduler, IScheduledCommand <TAggregate>, IDisposable> func)
            where TAggregate : IEventSourced
        {
            var scheduler = Clock.Current.IfTypeIs <VirtualClock>()
                            .Then(c => (IScheduler)c.Scheduler)
                            .Else(() => TaskPoolScheduler.Default);

            return(scheduler.Schedule(scheduledCommand, dueTime, func));
        }
        public static async Task <ScheduledCommandResult> ApplyScheduledCommand <TAggregate>(
            this IEventSourcedRepository <TAggregate> repository,
            IScheduledCommand <TAggregate> scheduled,
            Func <Task <bool> > verifyPrecondition = null)
            where TAggregate : class, IEventSourced
        {
            TAggregate aggregate = null;
            Exception  exception = null;

            try
            {
                if (verifyPrecondition != null && !await verifyPrecondition())
                {
                    return(await FailScheduledCommand(repository,
                                                      scheduled,
                                                      new PreconditionNotMetException()));
                }

                aggregate = await repository.GetLatest(scheduled.AggregateId);

                if (aggregate == null)
                {
                    if (scheduled.Command is ConstructorCommand <TAggregate> )
                    {
                        var ctor = typeof(TAggregate).GetConstructor(new[] { scheduled.Command.GetType() });
                        aggregate = (TAggregate)ctor.Invoke(new[] { scheduled.Command });
                    }
                    else
                    {
                        // TODO: (ApplyScheduledCommand) this should probably be a different exception type.
                        throw new ConcurrencyException(
                                  string.Format("No {0} was found with id {1} so the command could not be applied.",
                                                typeof(TAggregate).Name, scheduled.AggregateId),
                                  new IEvent[] { scheduled });
                    }
                }
                else
                {
                    await aggregate.ApplyAsync(scheduled.Command);
                }

                await repository.Save(aggregate);

                return(new CommandSucceeded(scheduled));
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            return(await FailScheduledCommand(repository, scheduled, exception, aggregate));
        }
Esempio n. 31
0
        internal static async Task <ScheduledCommand> StoreScheduledCommand <TAggregate>(
            IScheduledCommand <TAggregate> scheduledCommand,
            Func <CommandSchedulerDbContext> createDbContext,
            Func <IScheduledCommand <TAggregate>, CommandSchedulerDbContext, Task <string> > clockNameForEvent)
            where TAggregate : class
        {
            ScheduledCommand storedScheduledCommand;

            using (var db = createDbContext())
            {
                var domainTime = Domain.Clock.Now();

                // get or create a clock to schedule the command on
                var clock = scheduledCommand.Clock as Clock;
                if (clock == null)
                {
                    var clockName = await clockNameForEvent(scheduledCommand, db);

                    var clockStartTime = scheduledCommand.Clock?.Now() ??
                                         domainTime;

                    clock = await GetOrAddSchedulerClock(
                        db,
                        clockName,
                        clockStartTime);
                }

                storedScheduledCommand = CreateStoredScheduledCommand(
                    scheduledCommand,
                    domainTime,
                    clock);

                if (scheduledCommand.IsDue() &&
                    !scheduledCommand.Command.RequiresDurableScheduling())
                {
                    storedScheduledCommand.NonDurable = true;
                    return(storedScheduledCommand);
                }

                Debug.WriteLine(
                    $"Storing command '{scheduledCommand.Command.CommandName}' ({scheduledCommand.TargetId}:{storedScheduledCommand.SequenceNumber}) on clock '{clock.Name}'");

                await SaveScheduledCommandToDatabase(db,
                                                     storedScheduledCommand,
                                                     scheduledCommand);
            }

            scheduledCommand.IfTypeIs <ScheduledCommand <TAggregate> >()
            .ThenDo(c => c.SequenceNumber = storedScheduledCommand.SequenceNumber);

            return(storedScheduledCommand);
        }
 private static string Description(IScheduledCommand <TAggregate> scheduledCommand)
 {
     return(new
     {
         Name = scheduledCommand.Command.CommandName,
         DueTime = scheduledCommand.DueTime.IfNotNull()
                   .Then(t => t.ToString("O"))
                   .Else(() => "[null]"),
         Clocks = Domain.Clock.Current.ToString(),
         scheduledCommand.AggregateId,
         scheduledCommand.ETag
     }.ToString());
 }
        internal static void EnsureCommandHasETag <TTarget>(this IScheduledCommand <TTarget> scheduledCommand)
        {
            var command = scheduledCommand.Command;

            if (String.IsNullOrEmpty(command.ETag))
            {
                command.IfTypeIs <Command>()
                .ThenDo(c => c.ETag = CommandContext.Current
                                      .IfNotNull()
                                      .Then(ctx => ctx.NextETag(scheduledCommand.TargetId))
                                      .Else(() => Guid.NewGuid().ToString("N").ToETag()));
            }
        }
        public async Task<bool> VerifyPrecondition(IScheduledCommand scheduledCommand)
        {
            if (scheduledCommand == null)
            {
                throw new ArgumentNullException("scheduledCommand");
            }

            if (scheduledCommand.DeliveryPrecondition == null)
            {
                return true;
            }

            using (var eventStore = createEventStoreDbContext())
            {
                return await eventStore.Events.AnyAsync(
                    e => e.AggregateId == scheduledCommand.DeliveryPrecondition.AggregateId &&
                         e.ETag == scheduledCommand.DeliveryPrecondition.ETag);
            }
        }
        public static async Task<bool> IsPreconditionSatisfied(
            this ICommandPreconditionVerifier preconditionVerifier,
            IScheduledCommand scheduledCommand)
        {
            if (preconditionVerifier == null)
            {
                throw new ArgumentNullException("preconditionVerifier");
            }

            var precondition = scheduledCommand.DeliveryPrecondition;

            if (precondition == null)
            {
                return true;
            }

            return await preconditionVerifier.HasBeenApplied(
                precondition.AggregateId, 
                precondition.ETag);
        }
        public async Task<bool> IsPreconditionSatisfied(IScheduledCommand scheduledCommand)
        {
            if (scheduledCommand == null)
            {
                throw new ArgumentNullException("scheduledCommand");
            }

            if (scheduledCommand.DeliveryPrecondition == null)
            {
                return true;
            }

            var aggregateId = scheduledCommand.DeliveryPrecondition.AggregateId.ToString();
            var etag = scheduledCommand.DeliveryPrecondition.ETag;

            return eventStreams.Values.Any(v =>
            {
                var eventsForAggregate = v.All(aggregateId).Result;

                return eventsForAggregate.Any(e => e.ETag == etag);
            });
        }
Esempio n. 37
0
 protected CommandDelivered(IScheduledCommand command) : base(command)
 {
 }
 public string ClockName(IScheduledCommand forCommand) => getClockName(forCommand);
 public string ClockName(IScheduledCommand forCommand)
 {
     return getClockName(forCommand);
 }
 internal CommandDeduplicated(IScheduledCommand command, string when) : base(command)
 {
     this.when = when;
 }
        private async Task Enqueue(IScheduledCommand scheduledCommand)
        {
            var message = new BrokeredMessage(scheduledCommand.ToJson())
            {
                SessionId = scheduledCommand.AggregateId.ToString()
            };

            if (scheduledCommand.DueTime != null)
            {
                message.ScheduledEnqueueTimeUtc = scheduledCommand.DueTime.Value.UtcDateTime.Add(MessageDeliveryOffsetFromCommandDueTime);
            }

            messageSubject.OnNext(scheduledCommand);

            using (new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
            {
                await queueClient.SendAsync(message);
            }
        }
Esempio n. 42
0
 public CommandScheduled(IScheduledCommand command, IClock clock = null) : base(command)
 {
     Clock = clock;
 }
Esempio n. 43
0
 public CommandSucceeded(IScheduledCommand command) : base(command)
 {
 }