コード例 #1
0
        public void Invoke(ReceiveLogicalMessageContext context, Action next)
        {
            var messageToHandle = context.LogicalMessage;

            // for now we cheat and pull it from the behavior context:
            var callbackInvoked = context.Get <bool>(CallbackInvocationBehavior.CallbackInvokedKey);

            var handlerTypedToInvoke = HandlerRegistry.GetHandlerTypes(messageToHandle.MessageType).ToList();

            if (!callbackInvoked && !handlerTypedToInvoke.Any())
            {
                var error = string.Format("No handlers could be found for message type: {0}", messageToHandle.MessageType);
                throw new InvalidOperationException(error);
            }

            foreach (var handlerType in handlerTypedToInvoke)
            {
                var loadedHandler = new MessageHandler
                {
                    Instance   = context.Builder.Build(handlerType),
                    Invocation = (handlerInstance, message) => HandlerInvocationCache.InvokeHandle(handlerInstance, message)
                };

                if (PipelineFactory.InvokeHandlerPipeline(loadedHandler).ChainAborted)
                {
                    //if the chain was aborted skip the other handlers
                    break;
                }
            }

            next();
        }
コード例 #2
0
        public void Should_invoke_handle_method()
        {
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubHandler), typeof(StubMessage));
            var handler = new StubHandler();

            HandlerInvocationCache.InvokeHandle(handler, new StubMessage());
            Assert.IsTrue(handler.HandleCalled);
        }
コード例 #3
0
        public void Should_have_passed_through_correct_message()
        {
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubHandler), typeof(StubMessage));
            var handler     = new StubHandler();
            var stubMessage = new StubMessage();

            HandlerInvocationCache.InvokeHandle(handler, stubMessage);
            Assert.AreEqual(stubMessage, handler.HandledMessage);
        }
コード例 #4
0
        public void AddHandler(Type messageType, object handler)
        {
            List <LoadedHandler> handlersForMessage;

            var loadedHandler = new LoadedHandler
            {
                Instance   = handler,
                Invocation = (handlerInstance, message) => HandlerInvocationCache.InvokeHandle(handlerInstance, message)
            };

            if (!messageHandlers.TryGetValue(messageType, out handlersForMessage))
            {
                messageHandlers[messageType] = new List <LoadedHandler> {
                    loadedHandler
                };
            }
            else
            {
                handlersForMessage.Add(loadedHandler);
            }
        }
コード例 #5
0
        public void RunNew()
        {
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubMessageHandler), typeof(StubMessage));
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubTimeoutHandler), typeof(StubTimeoutState));
            var handler1     = new StubMessageHandler();
            var handler2     = new StubTimeoutHandler();
            var stubMessage1 = new StubMessage();
            var stubMessage2 = new StubTimeoutState();

            HandlerInvocationCache.InvokeHandle(handler1, stubMessage1);
            HandlerInvocationCache.InvokeHandle(handler2, stubMessage2);

            var startNew = Stopwatch.StartNew();

            for (var i = 0; i < 100000; i++)
            {
                HandlerInvocationCache.InvokeHandle(handler1, stubMessage1);
                HandlerInvocationCache.InvokeHandle(handler2, stubMessage2);
            }
            startNew.Stop();
            Trace.WriteLine(startNew.ElapsedMilliseconds);
        }
コード例 #6
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);
        }