public bool PreInsertInstance(ConsumeContext <TMessage> context, out TSaga instance) { if (_insertOnInitial) { instance = _sagaFactory.Create(context); return(true); } instance = null; return(false); }
IOrderFulfillmentSaga GetSaga(IOrder order) { if (!_sagas.Keys.Exists(k => k == order.Id)) { _sagas.Add(order.Id, _sagaFactory.Create(order)); } var saga = _sagas[order.Id]; return(saga); }
public void Register <TMessage>(ISagaFactory <TSaga, TMessage> factory) { Register(typeof(TMessage), m => factory.Create((TMessage)m)); }
public async Task RunAsync <TM>(IMessageContext <TM> messageContext, CancellationToken cancellationToken = default) where TM : IMessage { var(state, lockId) = await GetStateAsync(messageContext, cancellationToken); if (state.IsCompleted()) { _logger.LogWarning($"Stopped processing message '{messageContext.Message.Id}', Saga '{state.Id}' was already marked as completed"); return; } if (state.CheckWasProcessed(messageContext.Message)) { _logger.LogWarning($"message '{messageContext.Message.Id}' was already processed by saga '{state.Id}'"); return; } var saga = _sagaFactory.Create(state); if (null == saga) { throw new SagaException($"unable to create Saga of type '{typeof(TS).FullName}'"); } if (saga is not IHandleMessage <TM> handler) { throw new ConsumerNotFoundException(typeof(TM)); } var transaction = await _transactionManager.StartTransactionAsync(cancellationToken); try { var policy = _policyFactory.Create <TM>(); if (policy is null) { await handler.HandleAsync(messageContext, cancellationToken); } else { await policy.WrapAsync(() => handler.HandleAsync(messageContext, cancellationToken)); } state.SetAsProcessed(messageContext.Message); await _sagaStateService.SaveAsync(state, lockId, cancellationToken); await transaction.CommitAsync(cancellationToken); } catch (Exception ex) { await transaction.RollbackAsync(cancellationToken); if (saga is not ICompensateMessage <TM> compensatingHandler) { throw; } await ExecuteCompensationAsync(compensatingHandler, messageContext, ex, state, lockId, cancellationToken); } }