示例#1
0
        private void HandleRequest(string request)
        {
            JToken payload;

            try
            {
                payload = JToken.Parse(request);
            }
            catch
            {
                _outputHandler.Send(new ParseError());
                return;
            }

            if (!_receiver.IsValid(payload))
            {
                _outputHandler.Send(new InvalidRequest());
                return;
            }

            var(requests, hasResponse) = _receiver.GetRequests(payload);
            if (hasResponse)
            {
                foreach (var response in requests.Where(x => x.IsResponse).Select(x => x.Response))
                {
                    var id = response.Id is string s?long.Parse(s) : response.Id is long l ? l : -1;

                    if (id < 0)
                    {
                        continue;
                    }

                    var tcs = _responseRouter.GetRequest(id);
                    if (tcs is null)
                    {
                        continue;
                    }

                    if (response is ServerResponse serverResponse)
                    {
                        tcs.SetResult(serverResponse.Result);
                    }
                    else if (response is ServerError serverError)
                    {
                        tcs.SetException(new JsonRpcException(serverError));
                    }
                }

                return;
            }

            foreach (var item in requests)
            {
                if (item.IsRequest)
                {
                    var descriptor = _requestRouter.GetDescriptor(item.Request);
                    if (descriptor is null)
                    {
                        continue;
                    }
                    var type = _requestProcessIdentifier.Identify(descriptor);
                    _requestRouter.StartRequest(item.Request.Id);
                    _scheduler.Add(
                        type,
                        item.Request.Method,
                        async() => {
                        try
                        {
                            var result = await _requestRouter.RouteRequest(descriptor, item.Request, CancellationToken.None);
                            if (result.IsError && result.Error is RequestCancelled)
                            {
                                return;
                            }
                            _outputHandler.Send(result.Value);
                        }
                        catch (Exception e)
                        {
                            _logger.LogCritical(Events.UnhandledRequest, e, "Unhandled exception executing request {Method}@{Id}", item.Request.Method, item.Request.Id);
                            // TODO: Should we rethrow or swallow?
                            // If an exception happens... the whole system could be in a bad state, hence this throwing currently.
                            throw;
                        }
                    }
                        );
                }

                if (item.IsNotification)
                {
                    var descriptor = _requestRouter.GetDescriptor(item.Notification);
                    if (descriptor is null)
                    {
                        continue;
                    }

                    // We need to special case cancellation so that we can cancel any request that is currently in flight.
                    if (descriptor.Method == JsonRpcNames.CancelRequest)
                    {
                        var cancelParams = item.Notification.Params?.ToObject <CancelParams>();
                        if (cancelParams == null)
                        {
                            continue;
                        }
                        _requestRouter.CancelRequest(cancelParams.Id);
                        continue;
                    }

                    var type = _requestProcessIdentifier.Identify(descriptor);
                    _scheduler.Add(
                        type,
                        item.Notification.Method,
                        DoNotification(descriptor, item.Notification)
                        );
                }

                if (item.IsError)
                {
                    // TODO:
                    _outputHandler.Send(item.Error);
                }
            }

            Func <Task> DoNotification(IHandlerDescriptor descriptor, Notification notification)
            {
                return(async() => {
                    try
                    {
                        await _requestRouter.RouteNotification(descriptor, notification, CancellationToken.None);
                    }
                    catch (Exception e)
                    {
                        _logger.LogCritical(Events.UnhandledNotification, e, "Unhandled exception executing notification {Method}", notification.Method);
                        // TODO: Should we rethrow or swallow?
                        // If an exception happens... the whole system could be in a bad state, hence this throwing currently.
                        throw;
                    }
                });
            }
        }
示例#2
0
 public Task <Unit> Handle(CancelParams notification, CancellationToken token)
 {
     _requestRouter.CancelRequest(notification.Id);
     return(Unit.Task);
 }