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); }
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); }
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)); } }