static void RpcCallback <T>(IntPtr userData, IntPtr err, IntPtr responseBuf) { var handle = GCHandle.FromIntPtr(userData); var context = (CallbackContext <T>)handle.Target; if (err != IntPtr.Zero) { var pitayaError = new PitayaError( PitayaCluster.pitaya_error_code(err), PitayaCluster.pitaya_error_message(err)); context.t.SetException(new PitayaException($"RPC call failed: ({pitayaError.Code}: {pitayaError.Message})")); return; } Int32 len; IntPtr resData = PitayaCluster.pitaya_buffer_data(responseBuf, out len); byte[] resBytes = GetDataFromRawPointer(resData, len); try { // An RPC message comes encoded as a Protos.Response protobuf message. // The data field of the message is going to be either encoded in protobuf or JSON, // which is taken care by our serializer variable var rpcResponse = new Protos.Response(); rpcResponse.MergeFrom(resBytes); if (rpcResponse.Error == null) { T remoteResponse = (T)context.serializer.Unmarshal(rpcResponse.Data.ToByteArray(), typeof(T)); context.t.SetResult(remoteResponse); } else { context.t.SetException(new PitayaException( "rpc failed: code={0} msg={1}", rpcResponse.Error.Code, rpcResponse.Error.Msg )); } } catch (Exception e) { context.t.SetException(new PitayaException( "failed to parse rpc response: {0} (payload={1})", e.Message, Encoding.UTF8.GetString(resBytes) )); } }
static void DispatchRpc(RpcClient rpcClient, IntPtr rpc, Protos.Request req) { Task.Run(async() => { var start = Stopwatch.StartNew(); var res = new Protos.Response(); try { res = await HandleRpc(rpcClient, req, req.Type); } catch (Exception e) { res = GetErrorResponse("PIT-500", e.Message); var innerMostException = e; while (innerMostException.InnerException != null) { innerMostException = innerMostException.InnerException; } Logger.Error("Exception thrown in handler: {0}", innerMostException.Message); #if NPITAYA_DEBUG Logger.Error("StackTrace: {0}", e.StackTrace); #endif } finally { start.Stop(); _metricsReporter?.ObserveHistogram(RPC_LATENCY_METRIC, (float)start.Elapsed.TotalSeconds, null); unsafe { byte[] responseData = res.ToByteArray(); Int32 responseLen = responseData.Length; fixed(byte *p = responseData) { IntPtr err = pitaya_rpc_respond(rpc, (IntPtr)p, responseLen); if (err != IntPtr.Zero) { pitaya_error_drop(err); Logger.Error("Failed to respond to rpc"); } } } } }); }
static void DispatchRpc(RpcClient rpcClient, IntPtr rpc, Protos.Request req) { Task.Run(async() => { var res = new Protos.Response(); try { res = await HandleRpc(rpcClient, req, req.Type); } catch (Exception e) { res = GetErrorResponse("PIT-500", e.Message); var innerMostException = e; while (innerMostException.InnerException != null) { innerMostException = innerMostException.InnerException; } Logger.Error("Exception thrown in handler: {0}", innerMostException.Message); #if NPITAYA_DEBUG Logger.Error("StackTrace: {0}", e.StackTrace); #endif } finally { unsafe { byte[] responseData = res.ToByteArray(); Int32 responseLen = responseData.Length; fixed(byte *p = responseData) { IntPtr err = pitaya_rpc_respond(rpc, (IntPtr)p, responseLen); if (err != IntPtr.Zero) { pitaya_error_drop(err); Logger.Error("Failed to respond to rpc"); } } } } }); }