/// <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); }
/// <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); } } } ; }