/// <summary>
        /// Dispatches the message to the saga and, based on the saga's state
        /// persists it or notifies of its completion to interested parties.
        /// </summary>
        /// <param name="saga"></param>
        /// <param name="message"></param>
        /// <param name="sagaIsPersistent"></param>
        protected virtual void HaveSagaHandleMessage(ISaga saga, object message, bool sagaIsPersistent)
        {
            if (message.IsTimeoutMessage())
            {
                DispatchTimeoutMessageToSaga(saga, message);
            }
            else
            {
                CallHandleMethodOnSaga(saga, message);
            }

            if (!saga.Completed)
            {
                if (!sagaIsPersistent)
                {
                    Persister.Save(saga.Entity);
                }
                else
                {
                    Persister.Update(saga.Entity);
                }
            }
            else
            {
                if (sagaIsPersistent)
                {
                    Persister.Complete(saga.Entity);
                }

                NotifyTimeoutManagerThatSagaHasCompleted(saga);
            }

            LogIfSagaIsFinished(saga);
        }
        /// <summary>
        /// Dispatches the message to the saga and, based on the saga's state
        /// persists it or notifies of its completion to interested parties.
        /// </summary>
        /// <param name="saga"></param>
        /// <param name="message"></param>
        /// <param name="sagaIsPersistent"></param>
        protected virtual void HaveSagaHandleMessage(ISaga saga, IMessage message, bool sagaIsPersistent)
        {
            var tm = message as TimeoutMessage;

            if (tm != null)
            {
                saga.Timeout(tm.State);
            }
            else
            {
                CallHandleMethodOnSaga(saga, message);
            }

            if (!saga.Completed)
            {
                if (!sagaIsPersistent)
                {
                    Persister.Save(saga.Entity);
                }
                else
                {
                    Persister.Update(saga.Entity);
                }
            }
            else
            {
                if (sagaIsPersistent)
                {
                    Persister.Complete(saga.Entity);
                }

                NotifyTimeoutManagerThatSagaHasCompleted(saga);
            }

            LogIfSagaIsFinished(saga);
        }
Beispiel #3
0
        /// <summary>
        /// Get Dispatcher
        /// </summary>
        /// <param name="messageHandlerType">Type of the message Handler</param>
        /// <param name="builder">Builder</param>
        /// <param name="message">Message</param>
        /// <returns>Saga Dispatcher</returns>
        public IEnumerable <Action> GetDispatcher(Type messageHandlerType, IBuilder builder, object message)
        {
            var entitiesHandled  = new List <IContainSagaData>();
            var sagaTypesHandled = new List <Type>();

            foreach (var finder in GetFindersFor(message, builder))
            {
                var  sagaEntityIsPersistent = true;
                var  sagaEntity             = UseFinderToFindSaga(finder, message);
                Type sagaType;

                if (sagaEntity == null)
                {
                    sagaType = Features.Sagas.GetSagaTypeToStartIfMessageNotFoundByFinder(message, finder);
                    if (sagaType == null)
                    {
                        continue;
                    }

                    if (sagaTypesHandled.Contains(sagaType))
                    {
                        continue; // don't create the same saga type twice for the same message
                    }
                    sagaEntity = CreateNewSagaEntity(sagaType);

                    sagaEntityIsPersistent = false;
                }
                else
                {
                    if (entitiesHandled.Contains(sagaEntity))
                    {
                        continue; // don't call the same saga twice
                    }
                    sagaType = Features.Sagas.GetSagaTypeForSagaEntityType(sagaEntity.GetType());
                }

                if (messageHandlerType.IsAssignableFrom(sagaType))
                {
                    yield return () =>
                           {
                               var saga = (ISaga)builder.Build(sagaType);

                               saga.Entity = sagaEntity;

                               try
                               {
                                   SagaContext.Current = saga;

                                   if (IsTimeoutMessage(message))
                                   {
                                       HandlerInvocationCache.InvokeTimeout(saga, message);
                                   }
                                   else
                                   {
                                       HandlerInvocationCache.InvokeHandle(saga, message);
                                   }

                                   if (!saga.Completed)
                                   {
                                       if (!sagaEntityIsPersistent)
                                       {
                                           Persister.Save(saga.Entity);
                                       }
                                       else
                                       {
                                           Persister.Update(saga.Entity);
                                       }
                                   }
                                   else
                                   {
                                       if (sagaEntityIsPersistent)
                                       {
                                           Persister.Complete(saga.Entity);
                                       }

                                       if (saga.Entity.Id != Guid.Empty)
                                       {
                                           NotifyTimeoutManagerThatSagaHasCompleted(saga);
                                       }
                                   }

                                   LogIfSagaIsFinished(saga);
                               }
                               finally
                               {
                                   SagaContext.Current = null;
                               }
                           }
                }
                ;

                sagaTypesHandled.Add(sagaType);
                entitiesHandled.Add(sagaEntity);
            }

            if (entitiesHandled.Count == 0)
            {
                yield return () =>
                       {
                           logger.InfoFormat("Could not find a saga for the message type {0} with id {1}. Going to invoke SagaNotFoundHandlers.", message.GetType().FullName, Bus.CurrentMessageContext.Id);

                           foreach (var handler in builder.BuildAll <IHandleSagaNotFound>())
                           {
                               logger.DebugFormat("Invoking SagaNotFoundHandler: {0}",
                                                  handler.GetType().FullName);
                               handler.Handle(message);
                           }
                       }
            }
            ;
        }

        IContainSagaData CreateNewSagaEntity(Type sagaType)
        {
            var sagaEntityType = Features.Sagas.GetSagaEntityTypeForSagaType(sagaType);

            if (sagaEntityType == null)
            {
                throw new InvalidOperationException("No saga entity type could be found for saga: " + sagaType);
            }

            var sagaEntity = (IContainSagaData)Activator.CreateInstance(sagaEntityType);

            sagaEntity.Id = CombGuid.Generate();

            if (Bus.CurrentMessageContext.ReplyToAddress != null)
            {
                sagaEntity.Originator = Bus.CurrentMessageContext.ReplyToAddress.ToString();
            }
            sagaEntity.OriginalMessageId = Bus.CurrentMessageContext.Id;

            return(sagaEntity);
        }
        /// <summary>
        /// Get Dispatcher
        /// </summary>
        /// <param name="messageHandlerType">Type of the message Handler</param>
        /// <param name="builder">Builder</param>
        /// <param name="message">Message</param>
        /// <returns>Saga Dispatcher</returns>
        public IEnumerable <Action> GetDispatcher(Type messageHandlerType, IBuilder builder, object message)
        {
            if (message.IsTimeoutMessage() && !message.TimeoutHasExpired())
            {
                yield return(() => Bus.HandleCurrentMessageLater());

                yield break;
            }

            var entitiesHandled  = new List <ISagaEntity>();
            var sagaTypesHandled = new List <Type>();

            foreach (var finder in GetFindersFor(message, builder))
            {
                bool        sagaEntityIsPersistent = true;
                ISagaEntity sagaEntity             = UseFinderToFindSaga(finder, message);
                Type        sagaType;

                if (sagaEntity == null)
                {
                    sagaType = Configure.GetSagaTypeToStartIfMessageNotFoundByFinder(message, finder);
                    if (sagaType == null)
                    {
                        continue;
                    }

                    if (sagaTypesHandled.Contains(sagaType))
                    {
                        continue; // don't create the same saga type twice for the same message
                    }
                    Type sagaEntityType = Configure.GetSagaEntityTypeForSagaType(sagaType);
                    sagaEntity = Activator.CreateInstance(sagaEntityType) as ISagaEntity;

                    if (sagaEntity != null)
                    {
                        if (message is ISagaMessage)
                        {
                            sagaEntity.Id = (message as ISagaMessage).SagaId;
                        }
                        else
                        {
                            sagaEntity.Id = GuidCombGenerator.Generate();
                        }

                        sagaEntity.Originator        = Bus.CurrentMessageContext.ReplyToAddress.ToString();
                        sagaEntity.OriginalMessageId = Bus.CurrentMessageContext.Id;

                        sagaEntityIsPersistent = false;
                    }
                }
                else
                {
                    if (entitiesHandled.Contains(sagaEntity))
                    {
                        continue; // don't call the same saga twice
                    }
                    sagaType = Configure.GetSagaTypeForSagaEntityType(sagaEntity.GetType());
                }

                if (messageHandlerType.IsAssignableFrom(sagaType))
                {
                    yield return () =>
                           {
                               var saga = (ISaga)builder.Build(sagaType);

                               saga.Entity = sagaEntity;

                               HandlerInvocationCache.Invoke(saga, message);

                               if (!saga.Completed)
                               {
                                   if (!sagaEntityIsPersistent)
                                   {
                                       Persister.Save(saga.Entity);
                                   }
                                   else
                                   {
                                       Persister.Update(saga.Entity);
                                   }
                               }
                               else
                               {
                                   if (sagaEntityIsPersistent)
                                   {
                                       Persister.Complete(saga.Entity);
                                   }

                                   NotifyTimeoutManagerThatSagaHasCompleted(saga);
                               }

                               LogIfSagaIsFinished(saga);
                           }
                }
                ;
                sagaTypesHandled.Add(sagaType);
                entitiesHandled.Add(sagaEntity);
            }

            if (entitiesHandled.Count == 0)
            {
                yield return () =>
                       {
                           logger.InfoFormat("Could not find a saga for the message type {0} with id {1}. Going to invoke SagaNotFoundHandlers.", message.GetType().FullName, Bus.CurrentMessageContext.Id);

                           foreach (var handler in builder.BuildAll <IHandleSagaNotFound>())
                           {
                               logger.DebugFormat("Invoking SagaNotFoundHandler: {0}",
                                                  handler.GetType().FullName);
                               handler.Handle(message);
                           }
                       }
            }
            ;
        }