/// <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&lt; t message&gt; 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());
                    }
                }
            }
        }
Exemplo n.º 2
0
        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();
                    }
                }
        }
Exemplo n.º 3
0
        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);
                }
            }
        }
Exemplo n.º 4
0
 public bool CanUseExistingInstance(IConsumeContext <TMessage> context)
 {
     return(_policy.CanUseExistingInstance(context));
 }
Exemplo n.º 5
0
        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();
                }
        }
Exemplo n.º 7
0
        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());
                }
            }
        }