Example #1
0
        public async Task RouteNotification(IRequestDescriptor <TDescriptor> descriptors, Notification notification, CancellationToken token)
        {
            using (_activityTracingStrategy?.ApplyInbound(notification) ?? Disposable.Empty)
            {
                using var debug = _logger.TimeDebug("Routing Notification {Method}", notification.Method);
                using var _     = _logger.BeginScope(
                          new[] {
                    new KeyValuePair <string, string?>("Method", notification.Method),
                    new KeyValuePair <string, string?>("Params", notification.Params?.ToString())
                }
                          );

                object? @params = null;
                if (!(descriptors.Default?.Params is null))
                {
                    if (descriptors.Default.IsDelegatingHandler)
                    {
                        _logger.LogTrace(
                            "Converting params for Notification {Method} to {Type}", notification.Method, descriptors.Default.Params.GetGenericArguments()[0].FullName
                            );
                        var o = notification.Params?.ToObject(descriptors.Default.Params.GetGenericArguments()[0], _serializer.JsonSerializer);
                        @params = Activator.CreateInstance(descriptors.Default.Params, o);
                    }
                    else
                    {
                        _logger.LogTrace("Converting params for Notification {Method} to {Type}", notification.Method, descriptors.Default.Params.FullName);
                        @params = notification.Params?.ToObject(descriptors.Default.Params, _serializer.JsonSerializer);
                    }
                }

                await Task.WhenAll(descriptors.Select(descriptor => InnerRoute(_serviceScopeFactory, descriptor, @params, token))).ConfigureAwait(false);
            }
Example #2
0
        private ProcessSchedulerDelegate BuildNotificationDelegate(IRequestDescriptor <IHandlerDescriptor?> descriptors, Notification notification)
        {
            return(async(cancellationToken) =>
            {
                using var timeoutCts = new CancellationTokenSource(_requestTimeout);
                using var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);

                using var timer = _logger.TimeDebug("Processing notification {Method}", notification.Method);
                try
                {
                    await _requestRouter.RouteNotification(descriptors, notification, combinedCts.Token).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    if (timeoutCts.IsCancellationRequested)
                    {
                        _logger.LogTrace("Notification {Method} was cancelled due to timeout", notification.Method);
                        return;
                    }

                    _logger.LogTrace("Notification {Method} was cancelled", notification.Method);
                }
                catch (Exception e)
                {
                    _logger.LogCritical(Events.UnhandledRequest, e, "Failed to handle notification {Method}", notification.Method);
                }
            });
        }
            public async Task <ErrorResponse> RouteRequest(IRequestDescriptor <IHandlerDescriptor> descriptors, Request request, CancellationToken cancellationToken)
            {
                _onRequestCallback?.Invoke();

                await Task.Delay(_routeDelay, cancellationToken).ConfigureAwait(false);

                var successfulResponse = new TestSuccessfulResponse(request.Id, request);

                return(new ErrorResponse(successfulResponse));
            }
Example #4
0
        private ProcessSchedulerDelegate BuildRequestDelegate(IRequestDescriptor <IHandlerDescriptor?> descriptors, Request request, RequestInvocationHandle handle)
        {
            return(async(cancellationToken) =>
            {
                try
                {
                    var result = await InvokeRequestAsync(cancellationToken).ConfigureAwait(false);

                    _outputHandler.Send(result.Value);
                }
                finally
                {
                    handle.Dispose();
                }
            });

            async Task <ErrorResponse> InvokeRequestAsync(CancellationToken cancellationToken)
            {
                using var timeoutCts  = new CancellationTokenSource(_requestTimeout);
                using var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(handle.CancellationTokenSource.Token, timeoutCts.Token, cancellationToken);

                using var timer = _logger.TimeDebug("Processing request {Method}:{Id}", request.Method, request.Id);
                try
                {
                    var result = await _requestRouter.RouteRequest(descriptors, request, combinedCts.Token).ConfigureAwait(false);

                    return(result);
                }
                catch (OperationCanceledException)
                {
                    if (timeoutCts.IsCancellationRequested)
                    {
                        _logger.LogTrace("Request {Method}:{Id} was cancelled, due to timeout", request.Method, request.Id);
                        return(new RequestCancelled(request.Id, request.Method));
                    }

                    _logger.LogTrace("Request {Method}:{Id} was cancelled", request.Method, request.Id);
                    return(new RequestCancelled(request.Id, request.Method));
                }
                catch (RpcErrorException e)
                {
                    _logger.LogCritical(Events.UnhandledRequest, e, "Failed to handle request {Method}:{Id}", request.Method, request.Id);
                    return(new RpcError(
                               request.Id,
                               request.Method,
                               new ErrorMessage(e.Code, e.Message, e.Error)));
                }
                catch (Exception e)
                {
                    _logger.LogCritical(Events.UnhandledRequest, e, "Failed to handle request {Method}:{Id}. Unhandled exception", request.Method, request.Id);
                    return(new InternalError(request.Id, request.Method, e.ToString()));
                }
            }
        }
        public override void InvokeNotification(IRequestDescriptor <IHandlerDescriptor?> descriptor, Notification notification)
        {
            if (descriptor.Default is null)
            {
                throw new ArgumentNullException(nameof(descriptor.Default));
            }

            var type = _requestProcessIdentifier.Identify(descriptor.Default);
            var schedulerDelegate = RouteNotification(descriptor, notification);

            _processScheduler.Add(type, notification.Method, schedulerDelegate);
        }
 private SchedulerDelegate RouteNotification(
     IRequestDescriptor <IHandlerDescriptor?> descriptors,
     Notification notification) =>
 (_, scheduler) =>
 // ITS A RACE!
 Observable.Amb(
     Observable.Timer(_options.RequestTimeout, scheduler)
     .Select(_ => Unit.Default)
     .Do(
         _ => _logger.LogTrace("Notification was cancelled due to timeout")
         ),
     Observable.FromAsync(
            public async Task RouteNotification(IRequestDescriptor <IHandlerDescriptor> descriptors, Notification notification, CancellationToken cancellationToken)
            {
                try
                {
                    await Task.Delay(_routeDelay, cancellationToken).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    OnNotificationCancelled?.Invoke(notification);
                    throw;
                }

                OnNotificationCompleted?.Invoke(notification);
            }
        public override RequestInvocationHandle InvokeRequest(IRequestDescriptor <IHandlerDescriptor?> descriptor, Request request)
        {
            if (descriptor.Default is null)
            {
                throw new ArgumentNullException(nameof(descriptor.Default));
            }

            var handle = new RequestInvocationHandle(request);
            var type   = _requestProcessIdentifier.Identify(descriptor.Default);

            var schedulerDelegate = RouteRequest(descriptor, request, handle);

            _processScheduler.Add(type, $"{request.Method}:{request.Id}", schedulerDelegate);

            return(handle);
        }
Example #9
0
 Task IRequestRouter <IHandlerDescriptor?> .RouteNotification(IRequestDescriptor <IHandlerDescriptor?> descriptors, Notification notification, CancellationToken token) =>
 RouteNotification(
        private SchedulerDelegate RouteRequest(
            IRequestDescriptor <IHandlerDescriptor?> descriptor,
            Request request,
            RequestInvocationHandle handle)
        {
            var cts = handle.CancellationTokenSource;

            return((contentModifiedToken, scheduler) =>
                   Observable.Create <ErrorResponse>(
                       observer => {
                // ITS A RACE!
                var sub = Observable.Amb(
                    contentModifiedToken.Select(
                        _ => {
                    _logger.LogTrace(
                        "Request {Id} was abandoned due to content be modified", request.Id
                        );
                    return new ErrorResponse(
                        new ContentModified(request.Id, request.Method)
                        );
                }
                        ),
                    Observable.Timer(_options.RequestTimeout, scheduler).Select(
                        _ => new ErrorResponse(new RequestCancelled(request.Id, request.Method))
                        ),
                    Observable.FromAsync(
                        async ct => {
                    using var timer = _logger.TimeDebug(
                              "Processing request {Method} {ResponseId}", request.Method,
                              request.Id
                              );
                    ct.Register(cts.Cancel);
                    // ObservableToToken(contentModifiedToken).Register(cts.Cancel);
                    try
                    {
                        var result = await _requestRouter.RouteRequest(
                            descriptor, request, cts.Token
                            ).ConfigureAwait(false);
                        return result;
                    }
                    catch (OperationCanceledException)
                    {
                        _logger.LogTrace("Request {Id} was cancelled", request.Id);
                        return new RequestCancelled(request.Id, request.Method);
                    }
                    catch (RpcErrorException e)
                    {
                        _logger.LogCritical(
                            Events.UnhandledRequest, e,
                            "Failed to handle request {Method} {RequestId}", request.Method,
                            request.Id
                            );
                        return new RpcError(
                            request.Id, request.Method,
                            new ErrorMessage(e.Code, e.Message, e.Error)
                            );
                    }
                    catch (Exception e)
                    {
                        _logger.LogCritical(
                            Events.UnhandledRequest, e,
                            "Failed to handle request {Method} {RequestId}", request.Method,
                            request.Id
                            );
                        return new InternalError(request.Id, request.Method, e.ToString());
                    }
                }
                        )
                    )
                          .Subscribe(observer);
                return new CompositeDisposable(sub, handle);
            }
                       )
                   .Select(
                       response => {
                _outputHandler.Send(response.Value);
                return Unit.Default;
            }
                       ));
        }
 public abstract RequestInvocationHandle InvokeRequest(IRequestDescriptor <IHandlerDescriptor?> descriptor, Request request);
 public abstract void InvokeNotification(IRequestDescriptor <IHandlerDescriptor?> descriptor, Notification notification);