private async Task UpdateSagaAsync <TMessage>(TMessage message, ISaga saga, ISagaState state) where TMessage : class { var sagaType = saga.GetType(); var updatedSagaData = sagaType.GetProperty(nameof(ISaga <object> .Data))?.GetValue(saga); state.Update(saga.State, updatedSagaData); var logData = SagaLogData.Create(saga.Id, sagaType, message); if (_configuration.AllowConcurrentWrites) { var persistenceTasks = new[] { _repository.WriteAsync(state), _log.WriteAsync(logData) }; await Task.WhenAll(persistenceTasks).ConfigureAwait(false); } else { await _repository.WriteAsync(state); await _log.WriteAsync(logData); } }
private async Task ProcessAsync <TMessage>(Guid?nid, Type sagaType, Type sagaDataType, TMessage message, ISagaAction <TMessage> action, ISagaContext context = null) where TMessage : class { context = context ?? SagaContext.Empty; var saga = (ISaga)action; var id = nid ?? saga.ResolveId(message, context); var sagaData = await _repository.ReadAsync(id, sagaType).ConfigureAwait(false); if (sagaData is null) { if (!(action is ISagaStartAction <TMessage>)) { return; } sagaData = SagaData.Create(id, sagaType, SagaStates.Pending, Activator.CreateInstance(sagaDataType)); } else if (sagaData.State == SagaStates.Rejected) { return; } saga.Initialize(sagaData.SagaId, sagaData.State, sagaData.Data); var isError = false; try { await action.HandleAsync(message, context); } catch { isError = true; } var newSagaData = SagaData.Create(id, sagaType, saga.State, saga.Data); var sagaLogData = SagaLogData.Create(id, sagaType, message); var persistanceTasks = new Task[2] { _repository.WriteAsync(newSagaData), _sagaLog.SaveAsync(sagaLogData) }; await Task.WhenAll(persistanceTasks).ConfigureAwait(false); if (saga.State is SagaStates.Rejected || isError) { await CompensateAsync(saga, sagaType, context); } }