public async Task <TSideEffect> Process <TState, TSideEffect>(string requestId, string stateId, Func <TState, TSideEffect> handle, CancellationToken cancellationToken = default) where TState : State, new() { var(state, version) = await stateStore.Load <TState>(stateId, cancellationToken) .ConfigureAwait(false); if (state.TxId != null) { await FinishTransaction(stateId, state, version, cancellationToken) .ConfigureAwait(false); } var outboxState = await outboxStore.Get(requestId, cancellationToken); if (outboxState != null) { return(JsonConvert.DeserializeObject <TSideEffect>(outboxState.SideEffect)); } var sideEffect = handle(state); state.TxId = Guid.NewGuid(); outboxState = new OutboxItem { Id = state.TxId.ToString(), RequestId = requestId, SideEffect = JsonConvert.SerializeObject(sideEffect) }; await outboxStore.Store(outboxState, cancellationToken) .ConfigureAwait(false); string nextVersion; try { nextVersion = await stateStore.Upsert(stateId, state, version, cancellationToken) .ConfigureAwait(false); } catch (Exception e) when(!(e is OperationCanceledException)) { await outboxStore.Delete(outboxState.Id, cancellationToken) .ConfigureAwait(false); throw; } await FinishTransaction(stateId, state, nextVersion, cancellationToken) .ConfigureAwait(false); return(sideEffect); }
public async Task <TSideEffect> Process <TState, TSideEffect>(string requestId, string stateId, Func <TState, TSideEffect> handle) where TState : State, new() { var(state, version) = await stateStore.Load <TState>(stateId); if (state.TxId != null) { await FinishTransaction(stateId, state, version); } var outboxState = await outboxStore.Get(requestId); if (outboxState == null) { var sideEffect = handle(state); state.TxId = Guid.NewGuid(); outboxState = new OutboxItem { Id = state.TxId.ToString(), RequestId = requestId, SideEffect = JsonConvert.SerializeObject(sideEffect) }; await outboxStore.Store(outboxState); string nextVersion; try { nextVersion = await stateStore.Upsert(stateId, state, version); } catch { await outboxStore.Delete(outboxState.Id); throw; } await FinishTransaction(stateId, state, nextVersion); return(sideEffect); } return(JsonConvert.DeserializeObject <TSideEffect>(outboxState.SideEffect)); }