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