public static async Task SagaOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { TransactionItem item = context.GetInput <TransactionItem>(); var commandProducers = new Dictionary <string, Func <Task <ActivityResult <ProducerResult> > > > { [nameof(ValidateTransferCommand)] = () => ActivityFactory.ProduceValidateTransferCommandAsync(item, context, log), [nameof(TransferCommand)] = () => ActivityFactory.ProduceTransferCommandAsync(item, context, log), [nameof(CancelTransferCommand)] = () => ActivityFactory.ProduceCancelTransferCommandAsync(item, context, log), [nameof(IssueReceiptCommand)] = () => ActivityFactory.ProduceIssueReceiptCommandAsync(item, context, log) }; var sagaStatePersisters = new Dictionary <string, Func <Task <bool> > > { [nameof(SagaState.Pending)] = () => SagaFactory.PersistSagaStateAsync(item, SagaState.Pending, context, log), [nameof(SagaState.Success)] = () => SagaFactory.PersistSagaStateAsync(item, SagaState.Success, context, log), [nameof(SagaState.Cancelled)] = () => SagaFactory.PersistSagaStateAsync(item, SagaState.Cancelled, context, log), [nameof(SagaState.Fail)] = () => SagaFactory.PersistSagaStateAsync(item, SagaState.Fail, context, log), }; try { var orchestrator = new DurableOrchestrator(commandProducers, sagaStatePersisters); SagaState sagaState = await orchestrator.OrchestrateAsync(item, context, log); log.LogInformation($@"Saga state = {nameof(sagaState)} [{context.InstanceId}]"); } catch (ArgumentException ex) { log.LogError(ex.Message); } }
} // sagaId的定义 public SagaInfo SetStateClone(SagaState newState) { var c = this.Clone(); c.State = newState; return(c); }
public SagaState ToSagaState() { var type = Type.GetType(StateType); var state = ContractlessMessagePackSerializer.Instance.BinaryDeSerialize(SagaState, type); var sagaState = new SagaState(Id, state); sagaState.SagaVersion = SagaVersion; return sagaState; }
public async Task Update(Guid correlationId, object state) { var table = await _tableService.GetTable(EVENT_STORE_TABLE_NAME, false).ConfigureAwait(false); var entity = new SagaState(correlationId, state); var insertOperation = TableOperation.InsertOrReplace(entity); await table.ExecuteAsync(insertOperation).ConfigureAwait(false); }
public Task HandleAsync( IDomainEvent <SagaTestAggregate, SagaTestAggregateId, SagaTestEventA> domainEvent, ISagaContext sagaContext, CancellationToken cancellationToken) { Publish(new SagaTestBCommand(domainEvent.AggregateIdentity)); State = SagaState.Running; return(Task.FromResult(0)); }
private static TransactionItem CreateValidTransactionItem(SagaState state) { return(new TransactionItem { Id = Guid.NewGuid().ToString(), AccountFromId = Guid.NewGuid().ToString(), AccountToId = Guid.NewGuid().ToString(), Amount = 100.00M, State = nameof(state) }); }
public async Task Saga_should_succeed_with_successful_compensation_workflow() { var transactionItem = CreateFakeTransactionItem(); var commandProducers = new Dictionary <string, Func <Task <ActivityResult <ProducerResult> > > > { [nameof(ValidateTransferCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }), [nameof(TransferCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }), [nameof(CancelTransferCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }), [nameof(IssueReceiptCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }) }; var sagaStatePersisters = new Dictionary <string, Func <Task <bool> > > { [nameof(SagaState.Pending)] = () => Task.Run(() => true), [nameof(SagaState.Success)] = () => Task.Run(() => true), [nameof(SagaState.Cancelled)] = () => Task.Run(() => true), }; var loggerMock = new Mock <ILogger>(); var mockContext = new Mock <IDurableOrchestrationContext>(); mockContext .Setup(x => x.WaitForExternalEvent <string>(nameof(Sources.Validator))) .ReturnsAsync(nameof(TransferValidatedEvent)); mockContext .SetupSequence(x => x.WaitForExternalEvent <string>(nameof(Sources.Transfer))) .ReturnsAsync(nameof(TransferSucceededEvent)) .ReturnsAsync(nameof(TransferCanceledEvent)); mockContext .Setup(x => x.WaitForExternalEvent <string>(nameof(Sources.Receipt))) .ReturnsAsync(nameof(OtherReasonReceiptFailedEvent)); var orchestrator = new DurableOrchestrator(commandProducers, sagaStatePersisters); SagaState sagaState = await orchestrator.OrchestrateAsync(transactionItem, mockContext.Object, loggerMock.Object); Assert.Equal(SagaState.Cancelled, sagaState); }
public static async Task <bool> PersistSagaStateAsync( TransactionItem transactionItem, SagaState state, IDurableOrchestrationContext context, ILogger log) { TransactionItem item = TransactionFactory.BuildTransactionItemByState(transactionItem, state); ActivityResult <TransactionItem> result = await PersistSagaStateAsync(context, item); if (!result.Valid) { log.LogError(result.ExceptionMessage); return(false); } return(true); }
public async Task <bool> SetSagaState(string sagaId, SagaState state, SagaState?oldState) { if (oldState == null) { _sagaInfos[sagaId] = _sagaInfos[sagaId].SetStateClone(state); return(true); } if (!_sagaInfos.ContainsKey(sagaId)) { return(true); } var oldInfo = _sagaInfos[sagaId]; return(_sagaInfos.TryUpdate(sagaId, oldInfo.SetStateClone(state), oldInfo)); }
private async Task UpdateState( SagaState sagaState, State initialState, State newState, SagaAction sagaActions) { sagaState.ExtendedData = JsonConvert.SerializeObject(newState.Value); await stateDAO.Update(sagaState); var sagaLog = new SagaStateLog { InitialState = JsonConvert.SerializeObject(initialState.Value), FinshedState = JsonConvert.SerializeObject(newState.Value), SagaId = sagaState.SagaInfoId, ActionId = sagaActions.Id }; await actionLogStateDAO.Save(sagaLog); }
private Mock <ISaga> Arrange_Woking_SagaStore(SagaState sagaState = SagaState.New) { var sagaMock = new Mock <ISaga>(); sagaMock .Setup(s => s.State) .Returns(sagaState); _sagaStoreMock .Setup(s => s.UpdateAsync( It.IsAny <ISagaId>(), It.IsAny <Type>(), It.IsAny <ISourceId>(), It.IsAny <Func <ISaga, CancellationToken, Task> >(), It.IsAny <CancellationToken>())) .Callback <ISagaId, Type, ISourceId, Func <ISaga, CancellationToken, Task>, CancellationToken>( (id, details, arg3, arg4, arg5) => arg4(sagaMock.Object, CancellationToken.None)) .ReturnsAsync(sagaMock.Object); return(sagaMock); }
public async Task Saga_should_not_be_orchestrated_with_invalid_events() { var transactionItem = CreateFakeTransactionItem(); var commandProducers = new Dictionary <string, Func <Task <ActivityResult <ProducerResult> > > > { [nameof(ValidateTransferCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }), [nameof(TransferCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }), [nameof(IssueReceiptCommand)] = () => Task.Run(() => new ActivityResult <ProducerResult> { Item = new ProducerResult() }) }; var sagaStatePersisters = new Dictionary <string, Func <Task <bool> > > { [nameof(SagaState.Pending)] = () => Task.Run(() => true), [nameof(SagaState.Success)] = () => Task.Run(() => true), [nameof(SagaState.Fail)] = () => Task.Run(() => true), }; var loggerMock = new Mock <ILogger>(); var mockContext = new Mock <IDurableOrchestrationContext>(); mockContext .Setup(x => x.WaitForExternalEvent <string>(nameof(Sources.Validator))) .ReturnsAsync(nameof(ReceiptIssuedEvent)); var orchestrator = new DurableOrchestrator(commandProducers, sagaStatePersisters); SagaState sagaState = await orchestrator.OrchestrateAsync(transactionItem, mockContext.Object, loggerMock.Object); Assert.Equal(SagaState.Fail, sagaState); }
public TestSaga(TestSagaId id) { Id = id; State = SagaState.New; }
public void Reject() => State = SagaState.Rejected;
public void Complete() => State = SagaState.Completed;
public void Initialize() { SagaId = Guid.NewGuid().ToString(); State = SagaState.Pending; }
private static ISagaState CreateSagaState(SagaId id, Type sagaType, Type dataType) { var sagaData = dataType != null?Activator.CreateInstance(dataType) : null; return(SagaState.Create(id, sagaType, SagaStates.Pending, sagaData)); }
public static bool IsEndState(this SagaState state) { return(state == SagaState.SUCCESS || state == SagaState.COMPENSATION_DONE || state == SagaState.COMPENSATION_FAIL); }
internal async Task Update(SagaState sagaState) { using var context = _serviceProvider.GetRequiredService <SagaContext>(); context.States.Update(sagaState); await context.SaveChangesAsync(); }
public static TransactionItem BuildTransactionItemByState(TransactionItem item, SagaState state) { return(new TransactionItem { Id = item.Id, AccountFromId = item.AccountFromId, AccountToId = item.AccountToId, Amount = item.Amount, State = state.ToString() }); }
public Task <bool> SetSagaState(string sagaId, SagaState state, SagaState?oldState) { return(Task.FromResult(true)); }