private IMessageInvoker MessageInvokerFactory(IHandlerScope arg) { var invoker = new MessageInvoker(arg); invoker.HandlerMissing += (sender, args) => { _log.Warn("Handler missing for " + args.Message.Body.GetType()); }; invoker.Logger = DiagnosticLog; invoker.HandlerInvoked += (sender, args) => { _log.Debug(args.Message.Body); if (args.Exception == null) { return; } Err.Report(args.Exception, new { args.Message.Body, HandlerType = args.Handler.GetType(), args.ExecutionTime }); _log.Error( $"Ran {args.Handler}, took {args.ExecutionTime.TotalMilliseconds}ms, but FAILED.", args.Exception); }; return(invoker); }
private void RegisterHandler(Type handlerType) { IEnumerable <MethodInfo> actions = GetHandlerActions(handlerType); foreach (MethodInfo action in actions) { Type messageType = action.GetParameters()[0].ParameterType; MessageInvoker invoker = CreateInvoker(messageType, handlerType, action); var subscription = new Subscription { MessageType = messageType, HandlerType = handlerType, Invoker = invoker, Priority = GetDispatchingPriority(handlerType, action) }; if (!_store.ContainsKey(subscription.MessageType)) { var comparer = Comparer <Subscription> .Create((d1, d2) => d1.Priority.CompareTo(d2.Priority)); _store[subscription.MessageType] = new SortedSet <Subscription>(comparer); } _store[subscription.MessageType].Add(subscription); } }
private IMessageInvoker MessageInvokerFactory(IHandlerScope arg) { var k = arg.ResolveDependency <IMessageHandler <FeedbackAttachedToIncident> >(); var invoker = new MessageInvoker(arg); invoker.HandlerMissing += (sender, args) => { _logger.Warn( "Failed to find a handler for " + args.Message.Body.GetType()); }; invoker.HandlerInvoked += (sender, args) => { if (args.Exception == null) { return; } Err.Report(args.Exception, new { args.Message, HandlerType = args.Handler.GetType(), args.ExecutionTime }); _logger.Error( $"Ran {args.Handler}, took {args.ExecutionTime.TotalMilliseconds}ms, but FAILED.", args.Exception); }; return(invoker); }
private QueueListener ConfigureQueueListener(ConfigurationContext context, string inboundQueueName, string outboundQueueName) { var inboundQueue = _messageQueueProvider.Open(inboundQueueName); var outboundQueue = inboundQueueName == outboundQueueName ? inboundQueue : _messageQueueProvider.Open(outboundQueueName); var scopeFactory = new ScopeWrapper(context.ServiceProvider); var router = new MessageRouter { ReportAnalyzerQueue = outboundQueue, AppQueue = _messageQueueProvider.Open("Messaging") }; var listener = new QueueListener(inboundQueue, router, scopeFactory) { RetryAttempts = new[] { TimeSpan.FromMilliseconds(500), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2) }, MessageInvokerFactory = scope => { var invoker = new MessageInvoker(scope); invoker.Logger += (level, name, message) => _logger.Debug("[" + name + "] " + message); invoker.InvokingHandler += (sender, args) => { _logger.Debug( $"Invoking {JsonConvert.SerializeObject(args.Message)} ({args.Handler.GetType()})."); }; return(invoker); }, Logger = DiagnosticLog }; listener.PoisonMessageDetected += (sender, args) => { Err.Report(args.Exception, new { args.Message.Body }); _logger.Error(inboundQueueName + " Poison message: " + args.Message.Body, args.Exception); }; listener.ScopeCreated += (sender, args) => { args.Scope.ResolveDependency <IPrincipalAccessor>().First().Principal = args.Principal; _logger.Debug(inboundQueueName + " Running " + args.Message.Body + ", Credentials: " + args.Principal.ToFriendlyString()); }; listener.ScopeClosing += (sender, args) => { if (args.Exception != null) { return; } var all = args.Scope.ResolveDependency <IAdoNetUnitOfWork>().ToList(); all[0].SaveChanges(); var queue = (DomainQueueWrapper)args.Scope.ResolveDependency <IDomainQueue>().First(); queue.SaveChanges(); }; listener.MessageInvokerFactory = MessageInvokerFactory; return(listener); }
public void CanInvokeProperly() { MessageInvoker <Test> .Invoke(this, new BaseMessage("a", new object[] { "abcd", "efgh" })) .Should().BeNull(); _invokedOne.Should().BeTrue(); ((bool)(MessageInvoker <Test> .Invoke(this, new BaseMessage("b", new object[] { 1234, 5678 })))) .Should().BeTrue(); _invokedTwo.Should().BeTrue(); }
public void RegisterMethod(MethodInfo method, object target = null) { var invoker = MessageInvoker.Create(method, target); #if UNITY_EDITOR if (items.ContainsKey(invoker.MessageType)) { UnityEngine.Debug.LogError(string.Format("消息类型重复: {0}", invoker.MessageType)); } #endif items.Add(invoker.MessageType, invoker); }
public void Should_require_a_query_handler() { var scope = Substitute.For <IHandlerScope>(); var result = new OneResult(); scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new object[0]); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); Func <Task> actual = () => sut.ProcessAsync(context, new OneQuery()); actual.Should().Throw <NoHandlerRegisteredException>(); }
Should_be_able_to_reply_with_null_since_that_indicates_that_the_requested_resource_is_not_found() { var scope = Substitute.For <IHandlerScope>(); var handler = new MyHandler(); var msg = new Message(new MyQuery()); var sut = new MessageInvoker(scope); var queryContext = new ExecuteQueriesInvocationContext(new ClaimsPrincipal(), sut); scope.Create(typeof(IQueryHandler <MyQuery, string>)).Returns(new object[] { handler }); await sut.ProcessAsync(queryContext, msg); queryContext.Replies.Should().NotBeEmpty(); }
public async Task Should_be_able_to_execute_query_sucessfully() { var scope = Substitute.For <IHandlerScope>(); var result = new OneResult(); var handler = new OneQueryHandler(result); scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler }); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); await sut.ProcessAsync(context, new OneQuery()); context.Replies.First().Body.Should().BeSameAs(result); }
public async Task Should_invoke_message_handler() { var scope = Substitute.For <IHandlerScope>(); var handler = new TestHandler <Simple>(); scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler }); var msg = new Message(new Simple()); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); await sut.ProcessAsync(context, msg); handler.Invoked.Should().BeTrue(); }
public void Should_abort_if_multiple_query_handlers_have_been_registered() { var scope = Substitute.For <IHandlerScope>(); var result = new OneResult(); var handler = new OneQueryHandler(result); scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler, handler }); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); Func <Task> actual = () => sut.ProcessAsync(context, new OneQuery()); actual.Should().Throw <OnlyOneQueryHandlerAllowedException>(); }
public async Task Should_be_able_to_reply_with_a_message() { var scope = Substitute.For <IHandlerScope>(); var handler = new MyHandler { Result = "Word!" }; var msg = new Message(new MyQuery()); var sut = new MessageInvoker(scope); var queryContext = new ExecuteQueriesInvocationContext(new ClaimsPrincipal(), sut); scope.Create(typeof(IQueryHandler <MyQuery, string>)).Returns(new object[] { handler }); await sut.ProcessAsync(queryContext, msg); queryContext.Replies[0].Body.Should().Be("Word!"); }
public void Should_report_all_failed_handlers_in_the_exception() { var scope = Substitute.For <IHandlerScope>(); var handler = new TestHandler <Simple>((ctx, msg2) => throw new InvalidOperationException("No Data :(")); var handler2 = new TestHandler <Simple>((ctx, msg2) => throw new DataException("Here comes Lore!")); scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler, handler2 }); var msg = new Message(new Simple()); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); Func <Task> actual = () => sut.ProcessAsync(context, msg); actual.Should().Throw <HandlersFailedException>() .And.FailedHandlers.Count.Should().Be(2); }
public void Should_let_exceptions_flow_to_allow_caller_to_decide_appropiate_response() { var scope = Substitute.For <IHandlerScope>(); var handler = new TestHandler <Simple>(); var handler2 = new TestHandler <Simple>((ctx, msg2) => throw new DataException("Here comes Lore!")); scope.Create(typeof(IMessageHandler <Simple>)).Returns(new[] { handler, handler2 }); var msg = new Message(new Simple()); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); Func <Task> actual = () => sut.ProcessAsync(context, msg); actual.Should().Throw <HandlersFailedException>() .And.FailedHandlers[0].Exception.Message.Should().Be("Here comes Lore!"); }
public async Task Should_be_able_To_query_and_get_a_result() { var serviceProvider = new ServiceCollection() .AddScoped <IQueryHandler <FindUser, FindUserResult>, FindUserHandler>() .BuildServiceProvider(); var scopeFactory = new MicrosoftHandlerScopeFactory(serviceProvider); FindUserResult actual; using (var scope = scopeFactory.CreateScope()) { var invoker = new MessageInvoker(scope); var bus = new ScopedQueryBus(invoker); actual = await bus.QueryAsync(new FindUser()); } actual.Should().NotBeNull(); }
public bool RegisterMethod(MethodInfo method, object target = null) { #if UNITY_EDITOR && !GX_UNITTEST if (IsValid(method) == false) { UnityEngine.Debug.LogWarning(string.Format("无法兼容的函数签名: {0}", method)); } #endif var invoker = MessageInvoker.Create(method, target); #if UNITY_EDITOR if (items.ContainsKey(invoker.MessageType)) { UnityEngine.Debug.LogWarning(string.Format("消息类型重复注册并覆盖: {0}", invoker.MessageType)); } #endif items[invoker.MessageType] = invoker; return(true); }
private IMessageInvoker CreateMessageInvoker(IServiceProvider x) { var provider = (ServiceProvider)x; var invoker = new MessageInvoker(new HandlerScopeWrapper(provider)); invoker.HandlerMissing += (sender, args) => { _log.Error("No handler for " + args.Message.Body.GetType()); try { throw new NoHandlerRegisteredException( "Failed to find a handler for " + args.Message.Body.GetType()); } catch (Exception ex) { Err.Report(ex, new { args.Message.Body }); } }; invoker.InvokingHandler += (sender, args) => { _log.Debug($"Invoking {JsonConvert.SerializeObject(args.Message)} ({args.Handler.GetType()})."); }; invoker.HandlerInvoked += (sender, args) => { _log.Debug($".. completed {args.Handler.GetType()}"); if (args.Exception == null) { return; } _log.Error( $"Ran {args.Handler}, took {args.ExecutionTime.TotalMilliseconds}ms, but FAILED.", args.Exception); Err.Report(args.Exception, new { args.Message.Body, HandlerType = args.Handler.GetType(), args.ExecutionTime }); }; return(invoker); }
internal static Task Execute(this MessageInvoker invoker, DispatchingContext context) { var invocationResult = invoker(context.HandlerInstance, context.MessageInstance); var awaitableResult = invocationResult as Task; if (awaitableResult == null) { context.Result = invocationResult; return(Task.CompletedTask); } if (awaitableResult.Status == TaskStatus.Created) { awaitableResult.Start(); } return(awaitableResult.ContinueWith(task => { if (task.IsFaulted) { //TODO throw appropriate exception! //throw taskResult.Exception; } if (task.IsCanceled) { throw new OperationCanceledException("The async Task operation was cancelled"); } if (!task.IsCompleted) { throw new InvalidOperationException("Unknown Task state"); } context.Result = task.GetResult(); })); }
private IMessageInvoker CreateMessageInvoker(IServiceLocator x) { var scope = new GriffinContainerScopeAdapter((IChildContainer)x); var invoker = new MessageInvoker(scope); invoker.HandlerMissing += (sender, args) => { try { throw new NoHandlerRegisteredException( "Failed to find a handler for " + args.Message.Body.GetType()); } catch (Exception ex) { Err.Report(ex, new { args.Message }); } }; invoker.HandlerInvoked += (sender, args) => { if (args.Exception == null) { return; } Err.Report(args.Exception, new { args.Message, HandlerType = args.Handler.GetType(), args.ExecutionTime }); _log.Error( $"Ran {args.Handler}, took {args.ExecutionTime.TotalMilliseconds}ms, but FAILED.", args.Exception); }; return(invoker); }
public async Task Should_invoke_second_level_queries_directly() { var scope = Substitute.For <IHandlerScope>(); var result = new OneResult(); QueryTwoResult expected = null; var handler = new OneQueryHandler(result, (messageContext, query) => { expected = messageContext.QueryAsync(new QueryTwo()).GetAwaiter().GetResult(); }); var result2 = new QueryTwoResult(); var handler2 = new QueryTwoHandler(result2); scope.Create(typeof(IQueryHandler <OneQuery, OneResult>)).Returns(new[] { handler }); scope.Create(typeof(IQueryHandler <QueryTwo, QueryTwoResult>)).Returns(new[] { handler2 }); var sut = new MessageInvoker(scope); var context = new ExecuteQueriesInvocationContext(ClaimsPrincipal.Current, sut); await sut.ProcessAsync(context, new OneQuery()); expected.Should().BeSameAs(result2, "because it should not be enqueued as queries that comes from the queue"); context.Replies.Count.Should().Be(1, "because only result from first queue should be enqueued"); context.Replies.First().Body.Should().Be(result); context.Messages.Should().BeEmpty("because no messages were enqueued by the handlers"); }
public bool RegisterMethod(MethodInfo method, object target = null) { var invoker = MessageInvoker.Create(method, target); if (invoker == null) { return(false); } #if UNITY_EDITOR if (items.ContainsKey(invoker.NetMessageType)) { UnityEngine.Debug.LogError(string.Format("消息类型重复: {0}", invoker.NetMessageType)); } #endif try { items.Add(invoker.NetMessageType, invoker); } catch (System.Exception e) { Engine.Utility.Log.Error("{0}:{1}", invoker.NetMessageType.ToString(), e.ToString()); } return(true); }