public void Send <TMessage>(Expression <Func <T, bool> > filter, ISagaPolicy <T, TMessage> policy, TMessage message, Action <T> consumerAction) where TMessage : class { using (ISession session = _sessionFactory.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { T[] existingSagas = session.Linq <T>() .Where(filter).ToArray(); bool foundExistingSagas = SendMessageToExistingSagas(existingSagas, policy, consumerAction, message, session.Delete); if (foundExistingSagas) { transaction.Commit(); return; } SendMessageToNewSaga(policy, message, saga => { consumerAction(saga); session.Save(saga); }, session.Delete); transaction.Commit(); } }
private async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance) where T : class { try { if (Log.IsDebugEnabled) { Log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, instance.CorrelationId, TypeMetadataCache <T> .ShortName); } var sagaConsumeContext = new V2DynamoDbEventStoreSagaConsumeContext <TSaga, T>(_connection, context, instance, _options); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await _connection.SaveEventsAsync(instance, _options); } } catch (SagaException sagaException) { if (Log.IsDebugEnabled) { Log.Error(sagaException.Message, sagaException); } throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public async Task Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { if (!context.CorrelationId.HasValue) { throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T)); } _logger.Debug($"SAGA: Send {context.Message.GetType().FullName}"); var sagaId = context.CorrelationId.Value; if (policy.PreInsertInstance(context, out var instance)) { await PreInsertSagaInstance <T>(instance, context.MessageId).ConfigureAwait(false); } if (instance == null) { instance = await GetSaga(sagaId); } if (instance == null) { var missingSagaPipe = new MissingPipe <T>(_connection, next); await policy.Missing(context, missingSagaPipe).ConfigureAwait(false); } else { await SendToInstance(context, policy, next, instance).ConfigureAwait(false); } }
async Task SendToInstance <T>( ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance ) where T : class { try { var sagaConsumeContext = new EventStoreSagaConsumeContext <TSaga, T>(_connection, context, instance); sagaConsumeContext.LogUsed(); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await _connection.PersistSagaInstance(instance, context, _getEventMetadata); } } catch (SagaException) { throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public QuerySagaMessageConnector(IFilter <SagaConsumeContext <TSaga, TMessage> > consumeFilter, ISagaPolicy <TSaga, TMessage> policy, ISagaQueryFactory <TSaga, TMessage> queryFactory) : base(consumeFilter) { _policy = policy; _queryFactory = queryFactory; }
Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { var interceptPipe = new InterceptPipe <T>(_sagas, _received, next); var interceptPolicy = new InterceptPolicy <T>(_created, policy); return(_sagaRepository.Send(context, interceptPolicy, interceptPipe)); }
static async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, TSaga instance, IPipe <SagaConsumeContext <TSaga, T> > next, IDocumentSession session) where T : class { try { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, instance.CorrelationId, TypeMetadataCache <T> .ShortName); } var sagaConsumeContext = new MartenSagaConsumeContext <TSaga, T>(session, context, instance); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { session.Store(instance); session.SaveChanges(); } } catch (SagaException) { throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { try { List <TSaga> sagaInstances = await _collection.Find(context.Query.FilterExpression).ToListAsync().ConfigureAwait(false); if (!sagaInstances.Any()) { var missingPipe = new MissingPipe <TSaga, T>(_collection, next, _mongoDbSagaConsumeContextFactory); await policy.Missing(context, missingPipe).ConfigureAwait(false); } else { foreach (var instance in sagaInstances) { await SendToInstance(context, policy, next, instance).ConfigureAwait(false); } } } catch (SagaException sex) { context.LogFault(sex); throw; } catch (Exception ex) { context.LogFault(ex); throw new SagaException(ex.Message, typeof(TSaga), typeof(T), Guid.Empty, ex); } }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { using (_scope.BeginLifetimeScope(_name)) { await _repository.Send(context, policy, next); } }
public SagaPolicyTestDecorator(ISagaPolicy <TSaga, TMessage> policy, Guid sagaId, SagaList <TSaga> created) { _policy = policy; _sagaId = sagaId; _created = created; _removed = new SagaList <TSaga>(); }
async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance) where T : class { try { SagaConsumeContext <TSaga, T> sagaConsumeContext = _mongoDbSagaConsumeContextFactory.Create(_collection, context, instance); sagaConsumeContext.LogUsed(); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await UpdateMongoDbSaga(context, instance).ConfigureAwait(false); } } catch (SagaException sex) { context.LogFault(this, sex, instance?.CorrelationId); throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public async Task Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { using (_container.CreateChildContainer()) { await _repository.Send(context, policy, next).ConfigureAwait(false); } }
public async Task Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { var correlationId = context.CorrelationId ?? throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T)); try { await _repositoryContextFactory.Send(context, new SendSagaPipe <TSaga, T>(policy, next, correlationId)).ConfigureAwait(false); } catch (SagaException exception) { context.LogFault(this, exception); throw; } catch (DataException exception) { context.LogFault(this, exception); throw; } catch (Exception exception) { context.LogFault(this, exception); throw new SagaException(exception.Message, typeof(TSaga), typeof(T), Guid.Empty, exception); } }
public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { using (var session = _sessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { try { IList <TSaga> instances = await session.QueryOver <TSaga>() .Where(context.Query.FilterExpression) .ListAsync <TSaga>() .ConfigureAwait(false); if (instances.Count == 0) { var missingSagaPipe = new MissingPipe <T>(session, next); await policy.Missing(context, missingSagaPipe).ConfigureAwait(false); } else { await Task.WhenAll(instances.Select(instance => SendToInstance(context, policy, instance, next, session))).ConfigureAwait(false); } // TODO partial failure should not affect them all if (transaction.IsActive) { await transaction.CommitAsync().ConfigureAwait(false); } } catch (SagaException sex) { if (_log.IsErrorEnabled) { _log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", sex); } if (transaction.IsActive) { await transaction.RollbackAsync().ConfigureAwait(false); } throw; } catch (Exception ex) { if (_log.IsErrorEnabled) { _log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", ex); } if (transaction.IsActive) { await transaction.RollbackAsync().ConfigureAwait(false); } throw new SagaException(ex.Message, typeof(TSaga), typeof(T), Guid.Empty, ex); } } }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { using (_container.RequireScope()) { await _repository.Send(context, policy, next).ConfigureAwait(false); } }
async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance) where T : class { try { SagaConsumeContext <TSaga, T> sagaConsumeContext = _documentDbSagaConsumeContextFactory.Create(_client, _databaseName, _collectionName, context, instance, true, _requestOptions); sagaConsumeContext.LogUsed(); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await UpdateDocumentDbSaga(context, instance).ConfigureAwait(false); } } catch (SagaException) { throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance) where T : class { try { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, instance.CorrelationId, TypeMetadataCache <T> .ShortName); } var sagaConsumeContext = new RedisSagaConsumeContext <TSaga, T>(_clientsManager, context, instance); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { UpdateRedisSaga(instance); } } catch (SagaException) { throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { if (!context.CorrelationId.HasValue) { throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T)); } Guid sagaId = context.CorrelationId.Value; using (DbContext dbContext = _sagaDbContextFactory()) using (var transaction = dbContext.Database.BeginTransaction(_isolationLevel)) { bool inserted = false; TSaga instance; if (policy.PreInsertInstance(context, out instance)) { inserted = await PreInsertSagaInstance <T>(dbContext, instance, context.CancellationToken).ConfigureAwait(false); } try { if (instance == null) { instance = dbContext.Set <TSaga>().SingleOrDefault(x => x.CorrelationId == sagaId); } if (instance == null) { var missingSagaPipe = new MissingPipe <T>(dbContext, next); await policy.Missing(context, missingSagaPipe).ConfigureAwait(false); } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, instance.CorrelationId, TypeMetadataCache <T> .ShortName); } var sagaConsumeContext = new EntityFrameworkSagaConsumeContext <TSaga, T>(dbContext, context, instance); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); // if (inserted && !sagaConsumeContext.IsCompleted) // dbContext.Set<TSaga>().Update(instance); } await dbContext.SaveChangesAsync().ConfigureAwait(false); transaction.Commit(); } catch (Exception) { transaction.Rollback(); throw; } } }
public PropertySagaMessageSink(ISagaRepository <TSaga> repository, ISagaPolicy <TSaga, TMessage> policy, Expression <Func <TSaga, TMessage, bool> > selector) : base(repository, policy, new PropertySagaLocator <TSaga, TMessage>(repository, policy, selector), GetHandlers) { Selector = selector; }
public async Task Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { using (_container.GetNestedContainer()) { await _repository.Send(context, policy, next); } }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { if (!context.CorrelationId.HasValue) { throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T)); } var sagaId = context.CorrelationId.Value; using (var session = _store.DirtyTrackedSession()) { TSaga instance; if (policy.PreInsertInstance(context, out instance)) { PreInsertSagaInstance <T>(session, instance); } if (instance == null) { instance = session.Load <TSaga>(sagaId); } if (instance == null) { var missingSagaPipe = new MissingPipe <T>(session, next); await policy.Missing(context, missingSagaPipe).ConfigureAwait(false); } else { await SendToInstance(context, policy, instance, next, session).ConfigureAwait(false); } } }
async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, TSaga instance, IPipe <SagaConsumeContext <TSaga, T> > next, IDocumentSession session) where T : class { var sagaConsumeContext = new MartenSagaConsumeContext <TSaga, T>(session, context, instance); try { sagaConsumeContext.LogUsed(); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await session.SaveChangesAsync().ConfigureAwait(false); } } catch (SagaException sex) { sagaConsumeContext.LogFault(sex); throw; } catch (Exception ex) { sagaConsumeContext.LogFault(ex); throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public Task SendQuery <T>( SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next ) where T : class { throw new NotImplementedByDesignException("Redis saga repository does not support queries"); }
static string GetPolicy <TComponent, TMessage>(ISagaPolicy <TComponent, TMessage> policy) where TComponent : class, ISaga where TMessage : class { string description; Type policyType = policy.GetType().GetGenericTypeDefinition(); if (policyType == typeof(InitiatingSagaPolicy <,>)) { description = "Initiates New"; } else if (policyType == typeof(ExistingOrIgnoreSagaPolicy <,>)) { description = "Orchestrates Existing"; } else if (policyType == typeof(CreateOrUseExistingSagaPolicy <,>)) { description = "Initiates New Or Orchestrates Existing"; } else { description = policyType.ToFriendlyName(); } return(description); }
public CorrelatedSagaMessageConnector(IFilter <SagaConsumeContext <TSaga, TMessage> > consumeFilter, ISagaPolicy <TSaga, TMessage> policy, Func <ConsumeContext <TMessage>, Guid> correlationIdSelector) { _consumeFilter = consumeFilter; _policy = policy; _correlationIdSelector = correlationIdSelector; }
async Task SendToInstance <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next, TSaga instance) where T : class { try { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, instance.CorrelationId, TypeMetadataCache <T> .ShortName); } SagaConsumeContext <TSaga, T> sagaConsumeContext = _documentDbSagaConsumeContextFactory.Create(_client, _databaseName, _collectionName, context, instance, true, _requestOptions); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); if (!sagaConsumeContext.IsCompleted) { await UpdateDocumentDbSaga(context, instance).ConfigureAwait(false); } } catch (SagaException) { throw; } catch (Exception ex) { throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex); } }
public CorrelatedSagaFilter(ISagaRepository <TSaga> sagaRepository, ISagaPolicy <TSaga, TMessage> policy, IPipe <SagaConsumeContext <TSaga, TMessage> > messagePipe) { _sagaRepository = sagaRepository; _messagePipe = messagePipe; _policy = policy; }
public async Task Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { if (!context.CorrelationId.HasValue) { throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T)); } TSaga instance; if (policy.PreInsertInstance(context, out instance)) { await PreInsertSagaInstance(context, instance).ConfigureAwait(false); } if (instance == null) { instance = await _collection.Find(x => x.CorrelationId == context.CorrelationId).SingleOrDefaultAsync(context.CancellationToken).ConfigureAwait(false); } if (instance == null) { var missingSagaPipe = new MissingPipe <TSaga, T>(_collection, next, _mongoDbSagaConsumeContextFactory); await policy.Missing(context, missingSagaPipe).ConfigureAwait(false); } else { await SendToInstance(context, policy, next, instance).ConfigureAwait(false); } }
async Task SendToInstance <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, SagaInstance <TSaga> saga, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class { await saga.MarkInUse(context.CancellationToken).ConfigureAwait(false); try { if (saga.IsRemoved) { return; } if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, saga.Instance.CorrelationId, TypeMetadataCache <T> .ShortName); } SagaConsumeContext <TSaga, T> sagaConsumeContext = new InMemorySagaConsumeContext <TSaga, T>(context, saga.Instance, () => Remove(saga, context.CancellationToken)); await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false); } finally { saga.Release(); } }
public void Send <TMessage>(Expression <Func <T, bool> > filter, ISagaPolicy <T, TMessage> policy, TMessage message, Action <T> consumerAction) where TMessage : class { ISession session = NHibernateUnitOfWork.Current.Session; using (ITransaction transaction = session.BeginTransaction()) { IQueryable <T> existingSagas = session.Linq <T>() .Where(filter); bool foundExistingSagas = SendMessageToExistingSagas(existingSagas, policy, consumerAction, message, session.Delete); transaction.Commit(); if (foundExistingSagas) { return; } } using (ITransaction transaction = session.BeginTransaction()) { SendMessageToNewSaga(policy, message, saga => { consumerAction(saga); session.Save(saga); }, session.Delete); transaction.Commit(); } }