Esempio n. 1
0
        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);
        }
Esempio n. 2
0
 private void DispatchStepAsync(
     ExecuteStepCommand command)
 {
     Task.Run(async() =>
     {
         try
         {
             await DispatchStepSync(command);
         }
         catch (Exception ex)
         {
             await asyncErrorHandler.Handle(command.Saga, ex);
         }
     });
 }
Esempio n. 3
0
        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);
                }
            });
        }