示例#1
0
        private void InvokeOneWayMethod(IRequestContext context, object[] args, ContextChain chain)
        {
            Task.Run(() =>
            {
                // invoke method
                var invokeFuture = InvokeMethod(context, args);
                invokeFuture.ContinueWith(t =>
                {
                    if (t.Exception != null)
                    {
                        _logger.LogError(new EventId(0, "Thrift"), t.Exception, $"An error occurred execute method {_method.Name}[{_method.DeclaringType?.FullName}].");
                    }

                    chain.Done();
                });
            });
        }
        public Task <bool> ProcessCoreAsync(TProtocol protocolIn, TProtocol protocolOut, IRequestContext requestContext, out String methodName, out int sequenceId)
        {
            TMessage message = protocolIn.ReadMessageBegin();

            methodName = message.Name;
            sequenceId = message.SeqID;

            // lookup method
            ThriftMethodProcessor method;

            if (!this.Methods.TryGetValue(methodName, out method))
            {
                //TProtocolUtil.Skip(protocolIn, TType.Struct);
                CreateAndWriteApplicationException(protocolOut,
                                                   requestContext, methodName,
                                                   sequenceId,
                                                   TApplicationException.ExceptionType.UnknownMethod,
                                                   $"Invalid method name: '{methodName}'",
                                                   null,
                                                   _logger);

                return(Task.FromResult(true));
            }

            switch (message.Type)
            {
            case TMessageType.Call:
            case TMessageType.Oneway:
                // Ideally we'd check the message type here to make the presence/absence of
                // the "oneway" keyword annotating the method matches the message type.
                // Unfortunately most clients send both one-way and two-way messages as CALL
                // message type instead of using ONEWAY message type, and servers ignore the
                // difference.
                break;

            default:
                TProtocolUtil.Skip(protocolIn, TType.String);
                CreateAndWriteApplicationException(protocolOut,
                                                   requestContext,
                                                   methodName,
                                                   sequenceId,
                                                   TApplicationException.ExceptionType.InvalidMessageType,
                                                   $"Received invalid message type {message.Type} from client",
                                                   null,
                                                   _logger);
                return(Task.FromResult(true));
            }


            TaskCompletionSource <Boolean> resultFuture = new TaskCompletionSource <bool>();
            // invoke method
            ContextChain   context       = new ContextChain(this._eventHandlers, method.QualifiedName, requestContext);
            Task <Boolean> processResult = method.Process(protocolIn, protocolOut, sequenceId, context);

            processResult.ContinueWith(task =>
            {
                if (task.Exception == null)
                {
                    resultFuture.TrySetResult(task.Result);
                }
                else
                {
                    _logger.LogError(default(EventId), task.Exception, $"Failed to process method [{method.QualifiedName}] of service [{method.ServiceName}].");
                    resultFuture.TrySetException(task.Exception);
                }
            });
            return(resultFuture.Task);
        }
示例#3
0
        private Task <bool> CompleteMethodInvoke(Task <object> invokeTask, TProtocol outProtocol, int sequenceId, ContextChain contextChain, IRequestContext requestContext)
        {
            TaskCompletionSource <Boolean> resultFuture = new TaskCompletionSource <bool>();

            invokeTask.ContinueWith(t =>
            {
                if (t.Exception == null)
                {
                    var result = t.Result;
                    IRequestContext oldRequestContext = RequestContexts.GetCurrentContext();
                    RequestContexts.SetCurrentContext(requestContext);

                    // write success reply
                    try
                    {
                        contextChain.PreWrite(result);

                        WriteResponse(outProtocol,
                                      sequenceId,
                                      TMessageType.Reply,
                                      "success",
                                      (short)0,
                                      _successCodec,
                                      result);

                        contextChain.PostWrite(result);

                        resultFuture.TrySetResult(true);
                    }
                    catch (Exception e)
                    {
                        // An exception occurred trying to serialize a return value onto the output protocol
                        resultFuture.TrySetException(e);
                    }
                    finally
                    {
                        RequestContexts.SetCurrentContext(oldRequestContext);
                    }
                }
                else
                {
                    IRequestContext oldRequestContext = RequestContexts.GetCurrentContext();
                    RequestContexts.SetCurrentContext(requestContext);
                    try
                    {
                        contextChain.PreWriteException(t.Exception);
                        ExceptionProcessor exceptionCodec;

                        if (!_exceptionCodecs.TryGetValue(t.Exception.GetType(), out exceptionCodec))
                        {
                            // In case the method throws a subtype of one of its declared
                            // exceptions, exact lookup will fail. We need to simulate it.
                            // (This isn't a problem for normal returns because there the
                            // output codec is decided in advance.)
                            foreach (var entry in _exceptionCodecs)
                            {
                                if (entry.Key.GetTypeInfo().IsAssignableFrom(t.Exception.GetType()))
                                {
                                    exceptionCodec = entry.Value;
                                    break;
                                }
                            }
                        }

                        if (exceptionCodec != null)
                        {
                            contextChain.DeclaredUserException(t.Exception, exceptionCodec.Codec);
                            // write expected exception response
                            WriteResponse(
                                outProtocol,
                                sequenceId,
                                TMessageType.Reply,
                                "exception",
                                exceptionCodec.Id,
                                exceptionCodec.Codec,
                                t);
                            contextChain.PostWriteException(t.Exception);
                        }
                        else
                        {
                            contextChain.UndeclaredUserException(t.Exception);
                            // unexpected exception
                            TApplicationException applicationException =
                                ThriftServiceProcessor.CreateAndWriteApplicationException(
                                    outProtocol,
                                    requestContext,
                                    _method.Name,
                                    sequenceId,
                                    TApplicationException.ExceptionType.InternalError,
                                    $"Internal error processing '{_method.Name}'.",
                                    t.Exception,
                                    _logger);

                            contextChain.PostWriteException(applicationException);
                        }
                        if (!_oneway)
                        {
                            resultFuture.TrySetResult(true);
                        }
                    }
                    catch (Exception e)
                    {
                        // An exception occurred trying to serialize an exception onto the output protocol
                        resultFuture.TrySetException(e);
                    }
                    finally
                    {
                        RequestContexts.SetCurrentContext(oldRequestContext);
                    }
                }
            });
            return(resultFuture.Task);
        }
示例#4
0
        public Task <Boolean> Process(TProtocol inProtocol, TProtocol outProtocol, int sequenceId, ContextChain contextChain)
        {
            // read args
            contextChain.PreRead();
            Object[] args = ReadArguments(inProtocol);
            contextChain.PostRead(args);
            IRequestContext requestContext = RequestContexts.GetCurrentContext();

            inProtocol.ReadMessageEnd();
            if (!_oneway)
            {
                // invoke method
                var invokeFuture = InvokeMethod(requestContext, args);
                return(CompleteMethodInvoke(invokeFuture, outProtocol, sequenceId, contextChain, requestContext).ContinueWith(t =>
                {
                    contextChain.Done();
                    return t.Result;
                }));
            }
            else
            {
                InvokeOneWayMethod(requestContext, args, contextChain);
                //完全不用处理,因为客户端没有记录 oneway 的 sequence id,处理反而造成麻烦。
                //try
                //{
                //    WriteResponse(outProtocol,
                //                          sequenceId,
                //                          TMessageType.Reply,
                //                          "success",
                //                          (short)0,
                //                          _successCodec,
                //                          null);

                //}
                //catch (Exception e)
                //{
                //    TaskCompletionSource<Boolean> resultFuture = new TaskCompletionSource<bool>();
                //    resultFuture.TrySetException(e);
                //    return resultFuture.Task;
                //}
                return(Task.FromResult(true));
            }
        }