Ejemplo n.º 1
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);
                }
            }
        }