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