/// <summary> Enumerates get saga in this collection. </summary> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null. </exception> /// <exception cref="SagaException"> Thrown when a saga error condition occurs. </exception> /// <typeparam name="TMessage"> Type of the message. </typeparam> /// <param name="context"> The context. </param> /// <param name="sagaId"> Identifier for the saga. </param> /// <param name="selector"> The selector. </param> /// <param name="policy"> The policy. </param> /// <returns> An enumerator that allows foreach to be used to process get saga< t message> in this collection. </returns> public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>( IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { if (context == null) { throw new ArgumentNullException("context"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (policy == null) { throw new ArgumentNullException("policy"); } TSaga instance = Queryable.FirstOrDefault(x => x.CorrelationId == sagaId); if (instance == null) { if (policy.CanCreateInstance(context)) { yield return(CreateNewSagaAction(sagaId, selector, policy)); } else { if (Log.IsDebugEnabled) { Log.DebugFormat( "SAGA: {0} Ignoring Missing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } else { if (policy.CanUseExistingInstance(context)) { yield return(UseExistingSagaAction(sagaId, selector, policy, instance)); } else { if (Log.IsDebugEnabled) { Log.DebugFormat( "SAGA: {0} Ignoring Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } }
public IEnumerable <Guid> Find(IConsumeContext <TMessage> context) { Expression <Func <TSaga, bool> > filter = new SagaFilterExpressionConverter <TSaga, TMessage>(context.Message).Convert(_filterExpression); var sagaFilter = new SagaFilter <TSaga>(filter); int count = 0; foreach (var sagaId in _repository.Where(sagaFilter, x => x.CorrelationId)) { yield return(sagaId); count++; } if (count == 0) { if (_policy.CanCreateInstance(context)) { yield return(_policy.GetNewSagaId(context)); } } }
public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>(IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { using (ISession session = _sessionFactory.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { var instance = session.Get <TSaga>(sagaId, LockMode.Upgrade); if (instance == null) { if (policy.CanCreateInstance(context)) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Creating New {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { instance = policy.CreateInstance(x, sagaId); foreach (var callback in selector(instance, x)) { callback(x); } if (!policy.CanRemoveInstance(instance)) { session.Save(instance); } } catch (Exception ex) { var sex = new SagaException("Create Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } if (transaction.IsActive) { transaction.Rollback(); } throw sex; } }); } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Missing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } else { if (policy.CanUseExistingInstance(context)) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Using Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { session.Delete(instance); } } catch (Exception ex) { var sex = new SagaException("Existing Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } if (transaction.IsActive) { transaction.Rollback(); } throw sex; } }); } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } if (transaction.IsActive) { transaction.Commit(); } } }
public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>(IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { bool needToLeaveSagas = true; Monitor.Enter(_sagas); try { TSaga instance = _sagas[sagaId]; if (instance == null) { if (policy.CanCreateInstance(context)) { instance = policy.CreateInstance(context, sagaId); _sagas.Add(instance); lock (instance) { Monitor.Exit(_sagas); needToLeaveSagas = false; yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Creating New {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { _sagas.Remove(instance); } } catch (Exception ex) { var sex = new SagaException("Create Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } throw sex; } }); } } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Missing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } else { if (policy.CanUseExistingInstance(context)) { Monitor.Exit(_sagas); needToLeaveSagas = false; lock (instance) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Using Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { _sagas.Remove(instance); } } catch (Exception ex) { var sex = new SagaException("Existing Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } throw sex; } }); } } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } } finally { if (needToLeaveSagas) { Monitor.Exit(_sagas); } } }
public bool CanCreateInstance(IConsumeContext <TMessage> context) { return(_policy.CanCreateInstance(context)); }
public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>( IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { using (var session = this.documentStore.OpenSession()) { session.Advanced.UseOptimisticConcurrency = true; var instance = session.Load <TSaga>(sagaId); if (instance == null) { if (policy.CanCreateInstance(context)) { yield return(x => { try { instance = policy.CreateInstance(x, sagaId); foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { return; } session.Store(instance); session.SaveChanges(); } catch (Exception ex) { var sex = new SagaException( "Create Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); throw sex; } }); } } else { if (policy.CanUseExistingInstance(context)) { yield return(x => { try { const int NbtriesMax = 5; foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { session.Delete(instance); } try { session.SaveChanges(); } catch (ConcurrencyException) { if (x.RetryCount <= NbtriesMax) { x.RetryLater(); } else { throw; } } } catch (Exception ex) { var sex = new SagaException( "Existing Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); throw sex; } }); } } } }
public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>(IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { using (var db = dbProvider.Open()) using (var transaction = db.BeginTransaction()) { TSaga instance = db.Get <TSaga>(sagaId, transaction); Console.WriteLine("Got instance: {0}", instance == null ? "no instance" : instance.ToString()); if (instance == null) { if (policy.CanCreateInstance(context)) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Creating New {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { instance = policy.CreateInstance(x, sagaId); foreach (var callback in selector(instance, x)) { callback(x); } if (!policy.CanRemoveInstance(instance)) { try { db.Insert(instance, transaction); } catch (Exception) { // if insert fails update db.Update(instance, transaction); } } } catch (Exception ex) { var sex = new SagaException("Create Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } //if(transaction.IsActive) - Transaction is always active transaction.Rollback(); throw sex; } }); } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Missing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } else { Console.WriteLine("Have existing instance " + instance.ToString()); if (policy.CanUseExistingInstance(context)) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Using Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { db.Delete(instance, transaction); } else { db.Update(instance, transaction); } } catch (Exception ex) { var sex = new SagaException("Existing Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } //if(transaction.IsActive) - Transaction is always active transaction.Rollback(); throw sex; } }); } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } transaction.Commit(); } }
public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>( IConsumeContext <TMessage> context, Guid instanceId, InstanceHandlerSelector <TInstance, TMessage> selector, ISagaPolicy <TInstance, TMessage> policy) where TMessage : class { ////using (var transaction = new TransactionScope(TransactionScopeOption.RequiresNew)) ////TODO: Looks like Custom json deserialization is not performed when GetDocument is executed ////var getResult = bucket.GetDocument<TInstance>(instanceId.ToString()); ////if (!getResult.Success) ////{ //// var sagaException = new SagaException( //// getResult.Message, //// typeof(TInstance), //// typeof(TMessage), //// instanceId, //// getResult.Exception); //// this.log.Error(sagaException); //// throw sagaException; ////} ////else if ( //// getResult.Document != null //// && getResult.Document.Content != null) ////{ //// instance = getResult.Document.Content; ////} var instance = this .Where(s => s.CorrelationId.Equals(instanceId)) .FirstOrDefault(); if (instance == null) { if (policy.CanCreateInstance(context)) { yield return(action => { this.log.DebugFormat( "{0} Creating New instance {1} for {2}", typeof(TInstance).ToFriendlyName(), instanceId, typeof(TMessage).ToFriendlyName()); try { instance = policy.CreateInstance(action, instanceId); foreach (var callback in selector(instance, action)) { callback(action); } if (!policy.CanRemoveInstance(instance)) { this.RetrieveAndProcessResult( () => this.bucket.Insert(instanceId.ToString(), instance), result => { }); } } catch (Exception exception) { var sagaException = new SagaException( "Create Saga Instance Exception", typeof(TInstance), typeof(TMessage), instanceId, exception); this.log.Error(sagaException); throw sagaException; } }); } else { this.log.DebugFormat( "{0} Ignoring Missing instance {1} for {2}", typeof(TInstance).ToFriendlyName(), instanceId, typeof(TMessage).ToFriendlyName()); } } else { if (policy.CanUseExistingInstance(context)) { yield return(action => { this.log.DebugFormat( "{0} Using Existing instance {1} for {2}", typeof(TInstance).ToFriendlyName(), instanceId, typeof(TMessage).ToFriendlyName()); try { foreach (var callback in selector(instance, action)) { callback(action); } if (policy.CanRemoveInstance(instance)) { this.RetrieveAndProcessResult( () => this.bucket.Remove(instanceId.ToString()), result => { }); } else { this.RetrieveAndProcessResult( () => this.bucket.Replace(instanceId.ToString(), instance), result => { }); } } catch (Exception exception) { var sagaException = new SagaException( "Existing Saga Instance Exception", typeof(TInstance), typeof(TMessage), instanceId, exception); this.log.Error(sagaException); throw sagaException; } }); } else { this.log.DebugFormat( "{0} Ignoring Existing instance {1} for {2}", typeof(TInstance).ToFriendlyName(), instanceId, typeof(TMessage).ToFriendlyName()); } } }