Beispiel #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();
        }
Beispiel #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);
        }
Beispiel #3
0
        public void Should_invoke_timeout_method()
        {
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubHandler), typeof(StubTimeoutState));
            var handler = new StubHandler();

            HandlerInvocationCache.InvokeTimeout(handler, new StubTimeoutState());
            Assert.IsTrue(handler.TimeoutCalled);
        }
Beispiel #4
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);
        }
Beispiel #5
0
        public void Should_have_passed_through_correct_state()
        {
            HandlerInvocationCache.CacheMethodForHandler(typeof(StubHandler), typeof(StubTimeoutState));
            var handler   = new StubHandler();
            var stubState = new StubTimeoutState();

            HandlerInvocationCache.InvokeTimeout(handler, stubState);
            Assert.AreEqual(stubState, handler.HandledState);
        }
Beispiel #6
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);
            }
        }
Beispiel #7
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);
        }
Beispiel #8
0
        public void SetUp()
        {
            HandlerInvocationCache.Clear();

            SettingsHolder.Reset();
            SettingsHolder.SetDefault("Endpoint.SendOnly", false);

            Transport   = new FakeTransport();
            FuncBuilder = new FuncBuilder();
            Configure.GetEndpointNameAction = () => "TestEndpoint";
            const string localAddress = "endpointA";

            MasterNodeAddress = new Address(localAddress, "MasterNode");
            subscriptionPredicatesEvaluator = new SubscriptionPredicatesEvaluator();
            router                  = new StaticMessageRouter(KnownMessageTypes());
            handlerRegistry         = new MessageHandlerRegistry();
            MessageMetadataRegistry = new MessageMetadataRegistry
            {
                DefaultToNonPersistentMessages = false
            };

            try
            {
                Address.InitializeLocalAddress(localAddress);
            }
            catch // intentional
            {
            }

            MessageSerializer = new XmlMessageSerializer(MessageMapper);
            ExtensionMethods.GetStaticOutgoingHeadersAction = () => MessageHeaderManager.staticHeaders;
            gatewayAddress = MasterNodeAddress.SubScope("gateway");

            messageSender       = MockRepository.GenerateStub <ISendMessages>();
            subscriptionStorage = new FakeSubscriptionStorage();

            subscriptionManager = new MessageDrivenSubscriptionManager
            {
                Builder             = FuncBuilder,
                MessageSender       = messageSender,
                SubscriptionStorage = subscriptionStorage
            };

            FuncBuilder.Register <IMutateOutgoingTransportMessages>(() => headerManager);
            FuncBuilder.Register <IMutateIncomingMessages>(() => new FilteringMutator
            {
                SubscriptionPredicatesEvaluator = subscriptionPredicatesEvaluator
            });
            FuncBuilder.Register <IMutateOutgoingTransportMessages>(() => new SentTimeMutator());
            FuncBuilder.Register <IMutateIncomingTransportMessages>(() => subscriptionManager);
            FuncBuilder.Register <DefaultDispatcherFactory>(() => new DefaultDispatcherFactory());
            FuncBuilder.Register <EstimatedTimeToSLABreachCalculator>(() => SLABreachCalculator);
            FuncBuilder.Register <ExtractIncomingPrincipal>(() => new WindowsImpersonator());

            unicastBus = new UnicastBus
            {
                MasterNodeAddress = MasterNodeAddress,
                MessageSerializer = MessageSerializer,
                Builder           = FuncBuilder,
                MessageSender     = messageSender,
                Transport         = Transport,
                MessageMapper     = MessageMapper,
                MessagePublisher  = new StorageDrivenPublisher
                {
                    MessageSender       = messageSender,
                    SubscriptionStorage = subscriptionStorage
                },
                MessageDeferrer = new TimeoutManagerDeferrer
                {
                    MessageSender         = messageSender,
                    TimeoutManagerAddress = MasterNodeAddress.SubScope("Timeouts")
                },
                SubscriptionManager             = subscriptionManager,
                MessageMetadataRegistry         = MessageMetadataRegistry,
                SubscriptionPredicatesEvaluator = subscriptionPredicatesEvaluator,
                HandlerRegistry = handlerRegistry,
                MessageRouter   = router
            };
            bus = unicastBus;

            FuncBuilder.Register <IMutateOutgoingTransportMessages>(() => new CausationMutator {
                Bus = bus
            });
            FuncBuilder.Register <IBus>(() => bus);

            ExtensionMethods.SetHeaderAction = headerManager.SetHeader;
        }
Beispiel #9
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);
                           }
                       }
            }
            ;
        }
        public void SetUp()
        {
            transportDefinition = new Msmq();
            HandlerInvocationCache.Clear();

            SettingsHolder.Reset();
            SettingsHolder.SetDefault("Endpoint.SendOnly", false);

            Transport   = new FakeTransport();
            FuncBuilder = new FuncBuilder();
            Configure.GetEndpointNameAction = () => "TestEndpoint";
            subscriptionPredicatesEvaluator = new SubscriptionPredicatesEvaluator();
            router                  = new StaticMessageRouter(KnownMessageTypes());
            handlerRegistry         = new MessageHandlerRegistry();
            MessageMetadataRegistry = new MessageMetadataRegistry
            {
                DefaultToNonPersistentMessages = false
            };


            MessageSerializer = new XmlMessageSerializer(MessageMapper);
            //ExtensionMethods.GetStaticOutgoingHeadersAction = () => MessageHeaderManager.staticHeaders;
            gatewayAddress = MasterNodeAddress.SubScope("gateway");

            messageSender       = MockRepository.GenerateStub <ISendMessages>();
            subscriptionStorage = new FakeSubscriptionStorage();
            subscriptionManager = new MessageDrivenSubscriptionManager
            {
                Builder             = FuncBuilder,
                MessageSender       = messageSender,
                SubscriptionStorage = subscriptionStorage
            };

            var pipelineBuilder = new PipelineBuilder(FuncBuilder);

            pipelineFactory = new PipelineExecutor(FuncBuilder, pipelineBuilder);

            FuncBuilder.Register <IMessageSerializer>(() => MessageSerializer);
            FuncBuilder.Register <ISendMessages>(() => messageSender);

            FuncBuilder.Register <MessageAuditer>(() => new MessageAuditer());

            FuncBuilder.Register <LogicalMessageFactory>(() => new LogicalMessageFactory());

            FuncBuilder.Register <IMutateIncomingMessages>(() => new FilteringMutator
            {
                SubscriptionPredicatesEvaluator = subscriptionPredicatesEvaluator
            });
            FuncBuilder.Register <IMutateIncomingTransportMessages>(() => subscriptionManager);
            FuncBuilder.Register <EstimatedTimeToSLABreachCalculator>(() => SLABreachCalculator);
            FuncBuilder.Register <MessageMetadataRegistry>(() => MessageMetadataRegistry);

            FuncBuilder.Register <IMessageHandlerRegistry>(() => handlerRegistry);
            FuncBuilder.Register <ExtractIncomingPrincipal>(() => new WindowsImpersonator());
            FuncBuilder.Register <IMessageMapper>(() => MessageMapper);

            FuncBuilder.Register <ExtractLogicalMessagesBehavior>(() => new ExtractLogicalMessagesBehavior
            {
                MessageSerializer       = MessageSerializer,
                MessageMetadataRegistry = MessageMetadataRegistry,
            });
            FuncBuilder.Register <ImpersonateSenderBehavior>(() => new ImpersonateSenderBehavior
            {
                ExtractIncomingPrincipal = MockRepository.GenerateStub <ExtractIncomingPrincipal>()
            });

            FuncBuilder.Register <CreatePhysicalMessageBehavior>(() => new CreatePhysicalMessageBehavior());
            FuncBuilder.Register <PipelineBuilder>(() => pipelineBuilder);
            FuncBuilder.Register <PipelineExecutor>(() => pipelineFactory);
            FuncBuilder.Register <TransportDefinition>(() => transportDefinition);


            var messagePublisher = new StorageDrivenPublisher
            {
                MessageSender       = messageSender,
                SubscriptionStorage = subscriptionStorage
            };

            var deferrer = new TimeoutManagerDeferrer
            {
                MessageSender         = messageSender,
                TimeoutManagerAddress = MasterNodeAddress.SubScope("Timeouts")
            };

            FuncBuilder.Register <IDeferMessages>(() => deferrer);
            FuncBuilder.Register <IPublishMessages>(() => messagePublisher);

            unicastBus = new UnicastBus
            {
                MasterNodeAddress               = MasterNodeAddress,
                Builder                         = FuncBuilder,
                MessageSender                   = messageSender,
                Transport                       = Transport,
                MessageMapper                   = MessageMapper,
                SubscriptionManager             = subscriptionManager,
                SubscriptionPredicatesEvaluator = subscriptionPredicatesEvaluator,
                MessageRouter                   = router
            };
            bus = unicastBus;

            FuncBuilder.Register <IMutateOutgoingTransportMessages>(() => new CausationMutator {
                Bus = bus
            });
            FuncBuilder.Register <IBus>(() => bus);
            FuncBuilder.Register <UnicastBus>(() => unicastBus);
            new HeaderBootstrapper
            {
                Builder = FuncBuilder
            }.SetupHeaderActions();
        }