示例#1
0
        private static IServiceProvider GetServiceProvider()
        {
            var sp = RequestContexts.GetCurrentContext()?.GetServiceProvider();

            if (sp == null)
            {
                throw new SchubertException($"当前环境不存在一个 Swifty 请求上下文,不支持通过上下文获取 {nameof(IServiceProvider)}。");
            }
            return(sp);
        }
示例#2
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));
            }
        }
示例#3
0
        public WorkContext GetWorkContext()
        {
            var requestContext = RequestContexts.GetCurrentContext();

            return(requestContext?.GetServiceProvider()?.GetService <SwiftyWorkContext>());
        }
示例#4
0
        public Task AsynchronousInvoke(
            IRequestChannel channel,
            TChannelBufferInputTransport inputTransport,
            TChannelBufferOutputTransport outputTransport,
            TProtocol inputProtocol,
            TProtocol outputProtocol,
            int sequenceId,
            ClientContextChain contextChain,
            Object[] args)
        {
            //Mark: 微软没有提供 TaskCompletionSource 的非泛型类型,只能使用动态类型处理。
            TaskCompletionSourceEx future;

            if (_successCodec.Type != ThriftType.Void)
            {
                future = new TaskCompletionSourceEx(_successCodec.Type.CSharpType);
            }
            else
            {
                future = new TaskCompletionSourceEx(typeof(Object));
            }
            var requestContext = RequestContexts.GetCurrentContext();

            contextChain.PreWrite(args);
            outputTransport.ResetOutputBuffer();
            WriteArguments(outputProtocol, sequenceId, args);
            IByteBuffer requestBuffer = outputTransport.OutputBuffer.Copy();

            contextChain.PostWrite(args);

            requestBuffer.Retain();
            channel.SendAsynchronousRequest(requestBuffer, false,
                                            new RequestListener(
                                                onRequestSent: reqs =>
            {
                reqs.Release();
                if (this._oneway)
                {
                    try
                    {
                        ForceDoneChain(contextChain);
                        future.TrySetResult(null);
                    }
                    catch (Exception e)
                    {
                        ForceDoneChain(contextChain);
                        future.TrySetException(e);
                    }
                }
            },
                                                onResponseReceive: message =>
            {
                IRequestContext oldRequestContext = RequestContexts.GetCurrentContext();
                RequestContexts.SetCurrentContext(requestContext);
                try
                {
                    contextChain.PreRead();
                    inputTransport.SetInputBuffer(message);
                    WaitForResponse(inputProtocol, sequenceId);
                    Object results = ReadResponse(inputProtocol);
                    contextChain.PostRead(results);
                    ForceDoneChain(contextChain);
                    future.TrySetResult(results);
                }
                catch (Exception e)
                {
                    var wrapException = ThriftClientManager.WrapTException(e);
                    contextChain.PostReadException(e);
                    ForceDoneChain(contextChain);
                    future.TrySetException(wrapException);
                }
                finally
                {
                    RequestContexts.SetCurrentContext(oldRequestContext);
                }
            },
                                                onChannelError: e =>
            {
                if (requestBuffer.ReferenceCount > 0)
                {
                    requestBuffer.Release();
                }

                IRequestContext oldRequestContext = RequestContexts.GetCurrentContext();
                RequestContexts.SetCurrentContext(requestContext);
                try
                {
                    contextChain.PreReadException(e);
                    ForceDoneChain(contextChain);

                    var wrappedException = ThriftClientManager.WrapTException(e);
                    future.TrySetException(wrappedException);
                }
                finally
                {
                    RequestContexts.SetCurrentContext(oldRequestContext);
                }
            }
                                                ));
            return(future.Task);
        }
示例#5
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);
        }