public async Task <StateMachineProcessingResults> OnEventAsync(Type stateType, object state, ICorrelationEvent evt) { if (_stateMachineTypes == null) { throw new Exception("Saga configuration error. You need to configure the SagaStateMachineFactoryBuilder."); } var stateMachineType = _stateMachineTypes[stateType]; if (stateMachineType == null) { if (_stateMachineTypes.Values.Count == 0) { throw new Exception($"State machine type {stateType} not found. No state machines have been scanned. Did you add the assembly via SagaStateMachineFactoryBuilder.WithStateMachinesInAssembiles?"); } throw new Exception($"State machine type {stateType} not found out of {_stateMachineTypes.Values.Count} state machines."); } if (_container == null) { throw new Exception("IContainer supplied to SagaStateMachineFactoryBuilder is null."); } var stateMachine = _container.GetInstance(stateMachineType); var methodInfo = stateMachineType.GetMethod("ProcessNextStep", new[] { typeof(Guid), typeof(ICorrelationEvent), stateType, typeof(StateMachineProcessingResults) }); if (methodInfo == null || stateMachine == null) { throw new Exception($"No valid state machine {stateMachineType.Name} for state {stateType.Name}."); } { var result = new StateMachineProcessingResults(); await((Task)methodInfo?.Invoke(stateMachine, new[] { evt.CorrelationId, evt, state, result })).ConfigureAwait(false); return(result); } }
public async Task Initialize(T state) { var correlationId = Guid.NewGuid(); await _repository.Create(correlationId, state).ConfigureAwait(false); // create an event to represent the new state of the state machine, having an object instead of null // avoids having to perform a null check in each state machine var stateMachineCreatedEvent = new StateMachineCreatedEvent { CorrelationId = correlationId }; var firstStepResult = new StateMachineProcessingResults(); await ProcessNextStep(correlationId, stateMachineCreatedEvent, state, firstStepResult).ConfigureAwait(false); if (firstStepResult.IsSagaComplete) { // even though crazy, handle if a saga of a single command has been created await _repository.Delete(correlationId).ConfigureAwait(false); } else { await _repository.Update(correlationId, state).ConfigureAwait(false); } }
public abstract Task ProcessNextStep(Guid correlationId, ICorrelationEvent evt, T state, StateMachineProcessingResults results);