public async Task <ISaga> Publish(ISagaEvent @event, IDictionary <string, object> executionValues)
        {
            Type   eventType = @event.GetType();
            SagaID sagaId    = SagaID.From(@event.ID);

            ISagaModel model = sagaRegistrator.
                               FindModelForEventType(eventType);

            if (model == null)
            {
                throw new SagaEventNotRegisteredException(eventType);
            }

            ISaga newSaga = await CreateNewSagaIfRequired(model, sagaId, eventType);

            try
            {
                return(await ExecuteSaga(
                           @event,
                           model,
                           newSaga,
                           SagaID.From(newSaga?.Data?.ID ?? sagaId.Value),
                           executionValues,
                           false));
            }
            catch
            {
                //if (newSaga != null)
                //    await sagaPersistance.Remove(newSaga.Data.ID);

                throw;
            }
        }
        private async Task <ISaga> CreateNewSaga(ISagaModel model, SagaID id)
        {
            if (id == SagaID.Empty())
            {
                id = SagaID.New();
            }

            ISagaData data = (ISagaData)Activator.CreateInstance(model.SagaStateType);

            data.ID = id;

            ISaga saga = new Saga
            {
                Data          = data,
                ExecutionInfo = new SagaExecutionInfo
                {
                    ModelName = model.Name,
                    Created   = dateTimeProvider.Now,
                    Modified  = dateTimeProvider.Now
                },
                ExecutionState = new SagaExecutionState
                {
                    CurrentState = new SagaStartState().GetStateName(),
                    CurrentStep  = null
                }
            };

            return(saga);
        }
Beispiel #3
0
 public AsyncStepCompletedMessage(SagaID sagaID, string currentState,
                                  string currentStep, bool isCompensating, ISagaModel model)
 {
     SagaID         = sagaID;
     CurrentState   = currentState;
     CurrentStep    = currentStep;
     IsCompensating = isCompensating;
     Model          = model;
 }
        private async Task <ISaga> CreateNewSagaIfRequired(ISagaModel model, SagaID id, Type eventType)
        {
            ISaga saga = null;

            if (eventType != null)
            {
                bool isStartEvent = model.Actions.IsStartEvent(eventType);

                if (isStartEvent)
                {
                    saga = await CreateNewSaga(model, id);
                }
            }

            return(saga);
        }
Beispiel #5
0
        public async Task <ISaga> Publish(ISagaEvent @event, IDictionary <string, object> executionValues, Guid?parentId, SagaRunOptions runOptions)
        {
            runOptions = runOptions ?? new SagaRunOptions();

            Type   eventType = @event.GetType();
            SagaID sagaId    = SagaID.From(@event.ID);

            ISagaModel model = sagaRegistrator.
                               FindModelForEventType(eventType);

            if (model == null)
            {
                throw new SagaEventNotRegisteredException(eventType);
            }

            SagaID?parentSagaId = parentId == null ? (SagaID?)null : SagaID.From(parentId.Value);
            ISaga  newSaga      = await CreateNewSagaIfRequired(model, sagaId, parentSagaId, eventType);

            var id = SagaID.From(newSaga?.Data?.ID ?? sagaId.Value);

            try
            {
                var createdSaga = await ExecuteSaga(
                    @event,
                    model,
                    newSaga,
                    id,
                    executionValues,
                    false,
                    runOptions);

                return(createdSaga);
            }

            /*catch (SagaStopException ex)
             * {
             *   return await sagaPersistance.Get(id.Value);
             * }*/
            catch
            {
                //if (newSaga != null)
                //    await sagaPersistance.Remove(newSaga.Data.ID);

                throw;
            }
        }
Beispiel #6
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
                        }));
                    }
                }
            }
        }
        private async Task <ISaga> ExecuteSaga(
            ISagaEvent @event, ISagaModel model,
            ISaga saga,
            Guid sagaID,
            IDictionary <string, object> executionValues,
            bool resume)
        {
            bool sagaStarted = false;

            try
            {
                serviceProvider.
                GetRequiredService <ObservableRegistrator>().
                Initialize();

                await messageBus.
                Publish(new ExecutionStartMessage(SagaID.From(sagaID), model));

                sagaStarted = true;

                if (saga == null)
                {
                    saga = await sagaPersistance.Get(sagaID);
                }

                if (saga == null)
                {
                    throw new SagaInstanceNotFoundException();
                }

                if (saga.ExecutionState.IsDeleted)
                {
                    throw new CountNotExecuteDeletedSagaException(sagaID);
                }

                if (!resume)
                {
                    if (saga.IsIdle())
                    {
                        saga.ExecutionState.CurrentError = null;
                        saga.ExecutionState.ExecutionID  = ExecutionID.New();
                        if (model.HistoryPolicy == ESagaHistoryPolicy.StoreOnlyCurrentStep)
                        {
                            saga.ExecutionState.History.Clear();
                        }

                        saga.ExecutionValues.
                        Set(executionValues);

                        saga.ExecutionState.
                        CurrentEvent = @event ?? new EmptyEvent();
                    }
                    else
                    {
                        throw new SagaNeedToBeResumedException(saga.Data.ID);
                    }

                    logger.
                    LogInformation($"Executing saga: {saga.Data.ID}");
                }
                else
                {
                    logger.
                    LogInformation($"Resuming saga: {saga.Data.ID}");
                }

                ExecuteActionCommandHandler handler = serviceProvider.
                                                      GetRequiredService <ExecuteActionCommandHandler>();

                return(await handler.Handle(new ExecuteActionCommand
                {
                    Async = AsyncExecution.False(),
                    Saga = saga,
                    Model = model
                }));
            }
            catch (Exception ex)
            {
                if (sagaStarted)
                {
                    await messageBus.Publish(
                        new ExecutionEndMessage(SagaID.From(sagaID)));
                }

                if (ex is SagaStepException sagaStepException && sagaStepException?.OriginalException != null)
                {
                    throw sagaStepException.OriginalException;
                }

                throw;
            }
        }
 public ExecutionEndMessage(SagaID sagaId)
 {
     SagaId = sagaId;
 }
 public ExecutionStartMessage(SagaID saga, ISagaModel model)
 {
     SagaID     = saga;
     this.Model = model;
 }