/// <summary>
 /// Verifies that the command precondition has been met.
 /// </summary>
 private async Task <bool> PreconditionHasBeenMet(IScheduledCommand scheduledCommand)
 {
     return(await etagChecker.IsPreconditionSatisfied(scheduledCommand));
 }
Exemplo n.º 2
0
        private async Task ApplyScheduledCommand(
            IStore <TAggregate> store,
            IScheduledCommand <TAggregate> scheduled)
        {
            TAggregate aggregate = null;
            Exception  exception;

            try
            {
                if (!await etagChecker.IsPreconditionSatisfied(scheduled))
                {
                    await FailScheduledCommand(store,
                                               scheduled,
                                               new PreconditionNotMetException(scheduled.DeliveryPrecondition));

                    return;
                }

                aggregate = await store.Get(scheduled.TargetId);

                var isConstructorCommand = scheduled.Command is ConstructorCommand <TAggregate>;

                if (aggregate == null)
                {
                    if (isConstructorCommand)
                    {
                        var ctor = typeof(TAggregate).GetConstructor(new[] { scheduled.Command.GetType() });

                        if (ctor == null)
                        {
                            throw new InvalidOperationException($"No constructor was found on type {typeof(TAggregate)} for constructor command {scheduled.Command}.");
                        }

                        aggregate = (TAggregate)ctor.Invoke(new[] { scheduled.Command });
                    }
                    else
                    {
                        throw new PreconditionNotMetException(
                                  $"No {typeof(TAggregate).Name} was found with id {scheduled.TargetId} so the command could not be applied.");
                    }
                }
                else if (isConstructorCommand)
                {
                    throw new ConcurrencyException($"Command target having id {scheduled.TargetId} already exists");
                }
                else
                {
                    await aggregate.ApplyAsync(scheduled.Command);
                }

                await store.Put(aggregate);

                scheduled.Result = new CommandSucceeded(scheduled);

                return;
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            await FailScheduledCommand(store, scheduled, exception, aggregate);
        }