public void Enrich(Dictionary <string, string> properties, ICommand command, ICommandDispatchContext context) { if (command is IUserContextCommand userContextCommand) { properties["UserId"] = userContextCommand.AuthenticatedUserId.ToString(); } }
public CommandExecutionException(object command, Type handlerType, int handlerExecutionIndex, ICommandDispatchContext commandDispatchContext) { Command = command; HandlerType = handlerType; HandlerExecutionIndex = handlerExecutionIndex; CommandDispatchContext = commandDispatchContext; }
public async Task AuditPostDispatch(ICommand command, ICommandDispatchContext dispatchContext, long elapsedMilliseconds, CancellationToken cancellationToken) { if (_registeredPostDispatchAuditors.Count == 0) { return; } ICommandAuditSerializer serializer = _auditorSerializerFunc(); AuditItem auditItem = new AuditItem { AdditionalProperties = dispatchContext.AdditionalProperties.ToDictionary(x => x.Key, x => x.Value.ToString()), CommandId = null, CommandType = command.GetType().Name, CommandTypeFullName = command.GetType().AssemblyQualifiedName, CorrelationId = dispatchContext.CorrelationId, Depth = dispatchContext.Depth, DispatchedUtc = DateTime.UtcNow, SerializedCommand = serializer.Serialize(command), Type = AuditItem.PostDispatchType, DispatchTimeMs = elapsedMilliseconds }; // ReSharper disable once SuspiciousTypeConversion.Global - used by consumers of the package if (command is IIdentifiableCommand identifiableCommand) { auditItem.CommandId = identifiableCommand.CommandId; } _auditItemEnricherPipeline.Enrich(auditItem.AdditionalProperties, command, dispatchContext); await AuditPostDispatch(auditItem, cancellationToken); }
public CommandExecutionException(object command, Type handlerType, int handlerExecutionIndex, ICommandDispatchContext commandDispatchContext, string message, Exception innerException) : base(message, innerException) { Command = command; HandlerType = handlerType; HandlerExecutionIndex = handlerExecutionIndex; CommandDispatchContext = commandDispatchContext; }
public void Enrich(Dictionary <string, string> properties, ICommand command, ICommandDispatchContext context) { foreach (Type enricherType in _enrichers) { IAuditItemEnricher enricher = _enricherCreatorFunc(enricherType); enricher.Enrich(properties, command, context); } }
public void EnterCreatesInitialContext() { // Arrange Mock <ICommandCorrelationIdProvider> correlationIdProvider = new Mock <ICommandCorrelationIdProvider>(); Mock <ICommandDispatchContextEnrichment> commandContextEnrichment = new Mock <ICommandDispatchContextEnrichment>(); correlationIdProvider.Setup(x => x.Create()).Returns("someid"); AsyncLocalCommandScopeManager manager = new AsyncLocalCommandScopeManager(correlationIdProvider.Object, commandContextEnrichment.Object); // Act ICommandDispatchContext dispatchContext = manager.Enter(); // Assert Assert.Equal("someid", dispatchContext.CorrelationId); Assert.Equal(0, dispatchContext.Depth); }
public void EntryAfterFinalExitCreatesNewContext() { // Arrange Mock <ICommandCorrelationIdProvider> correlationIdProvider = new Mock <ICommandCorrelationIdProvider>(); Mock <ICommandDispatchContextEnrichment> commandContextEnrichment = new Mock <ICommandDispatchContextEnrichment>(); correlationIdProvider.Setup(x => x.Create()).Returns(() => Guid.NewGuid().ToString()); AsyncLocalCommandScopeManager manager = new AsyncLocalCommandScopeManager(correlationIdProvider.Object, commandContextEnrichment.Object); // Act ICommandDispatchContext initialDispatchContext = manager.Enter(); manager.Exit(); ICommandDispatchContext secondDispatchContext = manager.Enter(); // Assert Assert.NotEqual(initialDispatchContext, secondDispatchContext); Assert.NotEqual(initialDispatchContext.CorrelationId, secondDispatchContext.CorrelationId); }
public void RepeatedEntryAndMatchingxitDecrementsToMinusOne() { // Arrange Mock <ICommandCorrelationIdProvider> correlationIdProvider = new Mock <ICommandCorrelationIdProvider>(); Mock <ICommandDispatchContextEnrichment> commandContextEnrichment = new Mock <ICommandDispatchContextEnrichment>(); correlationIdProvider.Setup(x => x.Create()).Returns("someid"); AsyncLocalCommandScopeManager manager = new AsyncLocalCommandScopeManager(correlationIdProvider.Object, commandContextEnrichment.Object); // Act ICommandDispatchContext dispatchContext = manager.Enter(); manager.Enter(); manager.Enter(); manager.Exit(); manager.Exit(); manager.Exit(); // Assert Assert.Equal(-1, dispatchContext.Depth); }
public void EnterCreatesInitialContextWithEnrichedProperties() { // Arrange Mock <ICommandCorrelationIdProvider> correlationIdProvider = new Mock <ICommandCorrelationIdProvider>(); Mock <ICommandDispatchContextEnrichment> commandContextEnrichment = new Mock <ICommandDispatchContextEnrichment>(); commandContextEnrichment.Setup(x => x.GetAdditionalProperties()).Returns(new Dictionary <string, object> { { "MyProperty", 25 } }); correlationIdProvider.Setup(x => x.Create()).Returns("someid"); AsyncLocalCommandScopeManager manager = new AsyncLocalCommandScopeManager(correlationIdProvider.Object, commandContextEnrichment.Object); // Act ICommandDispatchContext dispatchContext = manager.Enter(); // Assert Assert.Equal("someid", dispatchContext.CorrelationId); Assert.Equal(25, dispatchContext.AdditionalProperties["MyProperty"]); Assert.Equal(0, dispatchContext.Depth); }
public async Task <TResult> ExecuteAsync <TResult>(ICommand <TResult> command, CancellationToken cancellationToken) { await new SynchronizationContextRemover(); ICommandDispatchContext dispatchContext = _commandScopeManager.GetCurrent(); Stopwatch stopwatch = _collectMetrics ? Stopwatch.StartNew() : null; try { TResult result = await ExecuteCommandWithHandlers(command, dispatchContext, cancellationToken); await _commandAuditPipeline.AuditExecution(command, dispatchContext, stopwatch?.ElapsedMilliseconds ?? 0, true, cancellationToken); return(result); } catch (Exception) { await _commandAuditPipeline.AuditExecution(command, dispatchContext, stopwatch?.ElapsedMilliseconds ?? 0, false, cancellationToken); throw; } }
private async Task <TResult> ExecuteCommandWithHandlers <TResult>(ICommand <TResult> command, ICommandDispatchContext dispatchContext, CancellationToken cancellationToken) { IReadOnlyCollection <IPrioritisedCommandHandler> handlers = _commandRegistry.GetPrioritisedCommandHandlers(command); if (handlers == null || handlers.Count == 0) { throw new MissingCommandHandlerRegistrationException(command.GetType(), "No command actors registered for execution of command"); } TResult result = default(TResult); int handlerIndex = 0; foreach (IPrioritisedCommandHandler handlerTemplate in handlers) { object baseHandler = null; try { baseHandler = _commandHandlerFactory.Create(handlerTemplate.CommandHandlerType); if (baseHandler is ICommandHandler handler) { result = await _commandHandlerExecuter.ExecuteAsync(handler, command, result, cancellationToken); } else { if (baseHandler is IPipelineAwareCommandHandler chainHandler) { PipelineAwareCommandHandlerResult <TResult> chainResult = await _pipelineAwareCommandHandlerExecuter.ExecuteAsync(chainHandler, command, result, cancellationToken); result = chainResult.Result; if (chainResult.ShouldStop) { break; } } else { throw new UnableToExecuteHandlerException("Unexpected result type"); } } } catch (Exception ex) { bool shouldContinue = await _commandExecutionExceptionHandler.HandleException(ex, baseHandler, handlerIndex, command, dispatchContext); if (!shouldContinue) { break; } } handlerIndex++; } return(result); }
public Task AuditWithNoPayload(Guid commandId, string commandType, ICommandDispatchContext dispatchContext) { throw new NotImplementedException(); }
public CommandDispatchException(TCommand command, ICommandDispatchContext commandDispatchContext, Type dispatcherType) { Command = command; CommandDispatchContext = commandDispatchContext; DispatcherType = dispatcherType; }
public CommandDispatchException(TCommand command, ICommandDispatchContext commandDispatchContext, Type dispatcherType, string message, Exception innerException) : base(message, innerException) { Command = command; CommandDispatchContext = commandDispatchContext; DispatcherType = dispatcherType; }
/// <summary> /// Constructor /// </summary> /// <param name="command">The command being dispatched</param> /// <param name="commandDispatchContext">The dispatch context</param> /// <param name="dispatcherType">The type of dispatcher in use</param> /// <param name="message">Error message</param> public CommandDispatchException(object command, ICommandDispatchContext commandDispatchContext, Type dispatcherType, string message) : base(message) { Command = command; CommandDispatchContext = commandDispatchContext; DispatcherType = dispatcherType; }
public Task <bool> HandleException <TResult>(Exception ex, object handler, int handlerExecutionIndex, ICommand <TResult> command, ICommandDispatchContext dispatchContext) { throw new DispatcherException($"Error occurred performing operation {command.GetType().Name}", ex); }
public async Task <CommandResult <TResult> > DispatchAsync <TResult>(ICommand <TResult> command, CancellationToken cancellationToken) { await new SynchronizationContextRemover(); ICommandDispatchContext dispatchContext = _commandScopeManager.Enter(); try { CommandResult <TResult> dispatchResult = null; CommandResult wrappedDispatchResult = null; ICommandExecuter executer = null; ICommandDispatcher dispatcher = null; ICommand unwrappedCommand = command; if (command is NoResultCommandWrapper wrappedCommand) { unwrappedCommand = wrappedCommand.Command; } // we specifically audit BEFORE dispatch as this allows us to capture intent and a replay to // occur even if dispatch fails // (there is also an audit opportunity after execution completes and I'm considering putting one in // on dispatch success) await _auditor.AuditPreDispatch(unwrappedCommand, dispatchContext, cancellationToken); try { Stopwatch stopwatch = _collectMetrics ? Stopwatch.StartNew() : null; Func <ICommandDispatcher> dispatcherFunc = _commandRegistry.GetCommandDispatcherFactory(command); if (dispatcherFunc != null) { dispatcher = dispatcherFunc(); if (command != unwrappedCommand) { wrappedDispatchResult = await dispatcher.DispatchAsync(unwrappedCommand, cancellationToken); } else { dispatchResult = await dispatcher.DispatchAsync(command, cancellationToken); } executer = dispatcher.AssociatedExecuter; } await _auditor.AuditPostDispatch(unwrappedCommand, dispatchContext, stopwatch?.ElapsedMilliseconds ?? -1, cancellationToken); if ((dispatchResult != null && dispatchResult.DeferExecution) || (wrappedDispatchResult != null && wrappedDispatchResult.DeferExecution)) { return(new CommandResult <TResult>(default(TResult), true)); } } catch (Exception ex) { throw new CommandDispatchException(unwrappedCommand, dispatchContext.Copy(), dispatcher?.GetType() ?? GetType(), "Error occurred during command dispatch", ex); } if (executer == null) { executer = AssociatedExecuter; } return(new CommandResult <TResult>(await executer.ExecuteAsync(command, cancellationToken), false)); } finally { _commandScopeManager.Exit(); } }
public Task <bool> HandleException <TResult>(Exception ex, object handler, int handlerExecutionIndex, ICommand <TResult> command, ICommandDispatchContext dispatchContext) { throw new CommandExecutionException(command, handler?.GetType(), handlerExecutionIndex, dispatchContext?.Copy(), "Error occurred during command execution", ex); }