public async Task <ISaga> Handle(ExecuteStepCommand command) { ISaga saga = command.Saga; ISagaStep step = command.SagaStep; ISagaAction sagaAction = command.SagaAction; ISagaModel model = command.Model; StepData stepData = GetOrCreateStepData(saga, step, model); MiddlewaresChain middlewaresChain = Middlewares.BuildFullChain( serviceProvider, SaveSaga, ExecuteStep); Exception executionError = null; try { await Middlewares.ExecuteChain( middlewaresChain, saga, step, stepData); stepData. SetSucceeded(saga.ExecutionState, dateTimeProvider); } catch (SagaStopException) { throw; return(null); } catch (Exception ex) { logger. LogError(ex, $"Saga: {saga.Data.ID}; Executing {(step.Async ? "async " : "")}step: {step.StepName}"); executionError = ex; stepData. SetFailed(saga.ExecutionState, dateTimeProvider, executionError.ToSagaStepException()); } finally { middlewaresChain. Clean(); stepData. SetEnded(saga.ExecutionState, dateTimeProvider); } string nextStepName = CalculateNextStepName( saga, step, sagaAction, stepData, executionError); SaveNextStep(saga, stepData, nextStepName); CheckIfSagaIsDeleted(saga); await sagaPersistance.Set(saga); return(saga); }
private void DispatchStepAsync( ExecuteStepCommand command) { Task.Run(async() => { try { await DispatchStepSync(command); } catch (Exception ex) { await asyncErrorHandler.Handle(command.Saga, ex); } }); }
private async Task <ISaga> DispatchStepSync( ExecuteStepCommand command) { using (IServiceScope scope = serviceScopeFactory.CreateScope()) { ExecuteStepCommandHandler stepExecutor = ActivatorUtilities. CreateInstance <ExecuteStepCommandHandler>(scope.ServiceProvider); ISaga saga = await stepExecutor. Handle(command); if (saga == null) { await messageBus.Publish( new ExecutionEndMessage(SagaID.From(command.Saga.Data.ID))); return(null); } else { if (saga.IsIdle()) { await messageBus.Publish( new ExecutionEndMessage(SagaID.From(saga.Data.ID))); if (saga.HasError()) { throw saga.ExecutionState.CurrentError; } return(saga); } else { return(await Handle(new ExecuteActionCommand() { Async = AsyncExecution.False(), Saga = saga, Model = command.Model })); } } } }
public async Task <ISaga> Handle(ExecuteActionCommand command) { ISaga saga = command.Saga; if (saga == null) { throw new SagaInstanceNotFoundException(command.Model.SagaStateType); } ISagaStep step = command.Model.Actions. FindStepForExecutionStateAndEvent(saga); ISagaAction action = command.Model. FindActionForStep(step); if (step.Async) { saga.ExecutionState.AsyncExecution = AsyncExecution.True(); } ExecuteStepCommand executeStepCommand = new ExecuteStepCommand { Saga = saga, SagaStep = step, SagaAction = action, Model = command.Model }; logger. LogDebug($"Saga: {saga.Data.ID}; Executing {(step.Async ? "async " : "")}step: {step.StepName}"); if (step.Async) { DispatchStepAsync(executeStepCommand); return(saga); } else { using (IServiceScope scope = serviceScopeFactory.CreateScope()) { return(await DispatchStepSync(scope.ServiceProvider, executeStepCommand)); } } }
private void DispatchStepAsync( ExecuteStepCommand command) { Task.Run(async() => { try { using (IServiceScope scope = serviceScopeFactory.CreateScope()) { // when Saga is forced to run asynchronously, then it can be resumed if (command?.Saga?.ExecutionState != null) { command.Saga.ExecutionState.CanBeResumed = true; } await DispatchStepSync(scope.ServiceProvider, command); } } catch (Exception ex) { await asyncErrorHandler.Handle(command.Saga, ex); } }); }