Beispiel #1
0
        private async Task InvokeQueryHandler(MessageInvocationContext context, Message message)
        {
            var resultType = GetQueryResultType(message.Body);

            var handlerType = typeof(IQueryHandler <,>).MakeGenericType(message.Body.GetType(), resultType);
            var handlers    = _scope.Create(handlerType).ToList();

            if (handlers.Count == 0)
            {
                throw new NoHandlerRegisteredException($"Missing handler for query '{message.Body}'.");
            }
            if (handlers.Count > 1)
            {
                throw new OnlyOneQueryHandlerAllowedException(
                          $"Queries may only have one handler, '{message.Body}' got [{string.Join(", ", handlers.Select(x => x.GetType().FullName))}].");
            }
            var handler = handlers[0];

            Task      task;
            Stopwatch sw    = null;
            var       args1 = new InvokingHandlerEventArgs(_scope, handler, message)
            {
                Principal = context.Principal
            };

            try
            {
                if (HandlerInvoked != null)
                {
                    sw = Stopwatch.StartNew();
                }

                InvokingHandler?.Invoke(this, args1);

                task = (Task)handler
                       .GetType()
                       .GetMethod("HandleAsync")
                       .Invoke(handler, new[] { context, message.Body });
                await task;

                sw?.Stop();
                var e = new HandlerInvokedEventArgs(_scope, handler, message, args1, sw?.Elapsed ?? TimeSpan.Zero)
                {
                    Principal = context.Principal
                };
                HandlerInvoked?.Invoke(this, e);
            }
            catch (Exception ex)
            {
                var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState,
                                                    sw?.Elapsed ?? TimeSpan.Zero)
                {
                    Exception = ex
                };
                HandlerInvoked?.Invoke(this, e);

                ExceptionDispatchInfo.Capture(ex).Throw();
                return;
            }

            var resultProperty = typeof(Task <>).MakeGenericType(resultType).GetProperty("Result");
            var result         = resultProperty.GetValue(task);
            await context.ReplyAsync(result);
        }
Beispiel #2
0
        private async Task InvokeMessageHandlers(IMessageContext context, Message message)
        {
            var messageType = message.Body.GetType();
            var handleMethodParameterTypes = new Type[] { typeof(IMessageContext), messageType };
            var type     = typeof(IMessageHandler <>).MakeGenericType(messageType);
            var handlers = _scope.Create(type).ToList();

            if (handlers.Count == 0)
            {
                Logger?.Invoke(LogLevel.Warning, message.MessageId.ToString("N"), "Missing handler for " + message.Body.GetType());
                var e = new HandlerMissingEventArgs(context.Principal, message, _scope);
                HandlerMissing?.Invoke(this, e);
                if (e.Handler != null)
                {
                    handlers.Add(e.Handler);
                }
                else if (e.ThrowException)
                {
                    throw new NoHandlerRegisteredException("Failed to find handler for '" + message.Body + "'.");
                }
                else
                {
                    return;
                }
            }


            if (InvokeHandlersInParallel)
            {
                var tasks = handlers.Select(async handler =>
                {
                    var mi       = handler.GetType().GetMethod("HandleAsync", handleMethodParameterTypes);
                    var task     = (Task)mi.Invoke(handler, new[] { context, message.Body });
                    Stopwatch sw = null;
                    var args1    = new InvokingHandlerEventArgs(_scope, handler, message)
                    {
                        Principal = context.Principal
                    };
                    try
                    {
                        if (HandlerInvoked != null)
                        {
                            sw = Stopwatch.StartNew();
                        }

                        Logger?.Invoke(LogLevel.Info, message.MessageId.ToString("N"), "Invoking " + handler.GetType());
                        InvokingHandler?.Invoke(this, args1);
                        await task;
                        sw?.Stop();

                        var e = new HandlerInvokedEventArgs(_scope, handler, message, args1,
                                                            sw?.Elapsed ?? TimeSpan.Zero)
                        {
                            Principal = context.Principal
                        };
                        HandlerInvoked?.Invoke(this, e);
                    }
                    catch (Exception ex)
                    {
                        Logger?.Invoke(LogLevel.Error, message.MessageId.ToString("N"),
                                       $"Handler failed: {handler.GetType()}, Exception: {ex}");
                        var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState,
                                                            sw?.Elapsed ?? TimeSpan.Zero)
                        {
                            Exception = ex,
                            Principal = context.Principal
                        };
                        HandlerInvoked?.Invoke(this, e);

                        ExceptionDispatchInfo.Capture(ex).Throw();
                    }
                }).ToArray();

                try
                {
                    await Task.WhenAll(tasks);
                }
                catch (Exception)
                {
                    var failedHandlers = new List <FailedHandler>();
                    for (var i = 0; i < handlers.Count; i++)
                    {
                        var task    = tasks[i];
                        var handler = handlers[i];
                        if (task.IsFaulted)
                        {
                            failedHandlers.Add(new FailedHandler
                            {
                                Exception   = task.Exception.InnerException,
                                HandlerType = handler.GetType()
                            });
                        }
                    }
                    throw new HandlersFailedException(message, failedHandlers);
                }
            }
            else
            {
                var failedHandlers = new List <FailedHandler>();
                foreach (var handler in handlers)
                {
                    var       mi    = handler.GetType().GetMethod("HandleAsync", handleMethodParameterTypes);
                    var       task  = (Task)mi.Invoke(handler, new[] { context, message.Body });
                    Stopwatch sw    = null;
                    var       args1 = new InvokingHandlerEventArgs(_scope, handler, message)
                    {
                        Principal = context.Principal
                    };
                    try
                    {
                        if (HandlerInvoked != null)
                        {
                            sw = Stopwatch.StartNew();
                        }

                        InvokingHandler?.Invoke(this, args1);
                        await task;
                        sw?.Stop();
                        var e = new HandlerInvokedEventArgs(_scope, handler, message, args1,
                                                            sw?.Elapsed ?? TimeSpan.Zero)
                        {
                            Principal = context.Principal
                        };
                        HandlerInvoked?.Invoke(this, e);
                    }
                    catch (Exception ex)
                    {
                        var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState,
                                                            sw?.Elapsed ?? TimeSpan.Zero)
                        {
                            Exception = ex,
                            Principal = context.Principal
                        };
                        HandlerInvoked?.Invoke(this, e);
                        failedHandlers.Add(new FailedHandler()
                        {
                            Exception = ex, HandlerType = handlers.GetType()
                        });
                    }
                }

                if (failedHandlers.Any())
                {
                    throw new HandlersFailedException(message, failedHandlers);
                }
            }
        }