private static async Task Execute(IServiceProvider services, IContext context, Command command) { QueueCommandResult result = await services .Send <QueueCommand, Task <QueueCommandResult> >(new QueueCommand(command, context)) .To <ICommandProcessor>(); await result.Completion; }
public QueueOperationDebouncer() { Register((QueueCommand q) => { return(_currentCommands.TryAdd(q.Command.ID, Nothing.Value) ? Next(q) : Task.FromResult(QueueCommandResult.AlreadyProcessing())); }); Register(async(ExecuteCommand e) => { try { await Next(e).Get(); } finally { _currentCommands.TryRemove(e.Command.ID, out _); } }); }
private async Task Handle(RunScript script, IContext context) { foreach (ScriptCommand scriptCommand in script.Script.Commands) { using (TransactionScope scope = new TransactionScope(_services, context)) { scope .Context .Set(new RequestTimeContext(DateTime.Now), true); Command command = new Command( scriptCommand.ID, scriptCommand.Message, scriptCommand.Target); QueueCommandResult result = await _services .Send <QueueCommand, Task <QueueCommandResult> >(new QueueCommand(command, scope.Context)) .To <ICommandProcessor>(); await result.Completion; } } }
public CommandPersister( IServiceProvider services, ICommandMetadataProvider metadataProvider, ContractTypeSerializer serializer ) { Register(async(QueueCommand q) => { var queueSource = new TaskCompletionSource <QueueCommandResultType>(); var ctx = new CommandPersisterContext(queueSource.Task); var resultType = QueueCommandResultType.Unknown; try { q.Context.Set(ctx, true); QueueCommandResult result = await Next(q).Get(); resultType = result.Type; if (result.Type == QueueCommandResultType.SuccessfullyQueued) { using (var scope = new TransactionScope(services, q.Context)) { scope.Context.Set(new TimestampContext(DateTime.Now), true); scope.Context.Set(new CommandContext(q.Command.ID), true); QueueHelper h = new QueueHelper( serializer, repository: scope.GetRepository <ServerCommand>(), command: q.Command, metadata: metadataProvider.Provide(q.Context) ); if (await h.LoadExisting()) { if (!h.ExistingMatchesCurrent()) { resultType = QueueCommandResultType.Rejected; return(QueueCommandResult.Rejected()); } if (h.ExistingCompletedSuccessfully()) { resultType = QueueCommandResultType.AlreadyExecuted; return(QueueCommandResult.AlreadyExecuted()); } } ctx.Command = await h.CompleteQueue(); await scope.CommitAsync(); } } return(result); } finally { queueSource.SetResult(resultType); } }); Register(async(ExecuteCommand e) => { var persisterCtx = e.Context.Get <CommandPersisterContext>(); if (await persisterCtx.QueueTask != QueueCommandResultType.SuccessfullyQueued) { return; } ServerCommand sc = persisterCtx.Command.NotNull(); IServiceProvider sp = e.Context.Get <IServiceProvider>(); sc.BeginExecution(DateTime.Now); await sp .GetRepository <ServerCommand>() .Save(sc); await sp.GetRequiredService <ITransaction>().CommitAsync(); try { await Next(e).Get(); // We have to use a new transaction here, because the oiginal one may time // out if the execution of the command takes very long. using (var scope = new TransactionScope(sp, e.Context)) { sc.EndExecution(DateTime.Now); await scope .GetRepository <ServerCommand>() .Save(sc); await scope.CommitAsync(); } } catch (Exception ex) when(!ex.IsCritical()) { using (var scope = new TransactionScope(services, e.Context)) { scope.Context.Set(new TimestampContext(DateTime.Now), true); scope.Context.Set(new CommandContext(e.Command.ID), true); sc.EndExecution(DateTime.Now, ex); await scope .GetRepository <ServerCommand>() .Save(sc); await scope.CommitAsync(); } throw; } }); }