internal LightweightSerializers <TRequest, TResponse> GetSerializers <TRequest, TResponse>(RpcProxyMethod proxyMethod) where TRequest : class where TResponse : class { lock (this.syncRoot) { if (this.proxyToSerializers.TryGetValue(proxyMethod, out var serializers)) { return((LightweightSerializers <TRequest, TResponse>)serializers); } var newSerializers = new LightweightSerializers <TRequest, TResponse>(this.serializer); this.proxyToSerializers.Add(proxyMethod, newSerializers); return(newSerializers); } }
#pragma warning disable CA2000 // Dispose objects before losing scope public IAsyncStreamingServerCall <TResponse> BeginStreamingServerCall <TRequest, TResponse>( RpcFrameType frameType, string operation, RpcRequestContext?context, TRequest request, LightweightSerializers <TRequest, TResponse> serializers, int callTimeout) where TRequest : class where TResponse : class { var streamingCall = new AsyncStreamingServerCall <TResponse>(serializers.Serializer, serializers.ResponseSerializer); int messageId = this.AddAwaitingResponse(streamingCall); try { RpcOperationFlags flags = 0; var cancellationToken = context != null ? context.CancellationToken : default; if (cancellationToken.CanBeCanceled) { cancellationToken.Register(() => this.CancelCall(messageId, operation)); flags |= RpcOperationFlags.CanCancel; } if (callTimeout > 0 && !RpcProxyOptions.RoundTripCancellationsAndTimeouts) { Task.Delay(callTimeout) .ContinueWith(t => this.TimeoutCall(messageId, operation, callTimeout), cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default) .Forget(); } var frame = new LightweightRpcFrame(frameType, messageId, operation, flags, (uint)callTimeout, context?.Headers); var writeState = this.BeginWrite(frame); this.WriteRequest(request, serializers.RequestSerializer, writeState); return(streamingCall); } catch (Exception e) { this.HandleCallError(messageId, e); streamingCall.DisposeAsync().Forget(); throw; } }
internal Task <TResponse> SendReceiveFrameAsync <TRequest, TResponse>( RpcFrameType frameType, string operation, RpcRequestContext?context, TRequest request, LightweightSerializers <TRequest, TResponse> serializers, int timeout) where TRequest : class { if (TraceEnabled) { // TODO: Logger.Trace("Begin SendReceiveFrameAsync {Operation}.", operation); } var tcs = new ResponseCompletionSource <TResponse>(serializers.Serializer, serializers.ResponseSerializer); int messageId = this.AddAwaitingResponse(tcs); try { RpcOperationFlags flags = 0; var cancellationToken = context != null ? context.CancellationToken : default; if (cancellationToken.CanBeCanceled) { cancellationToken.Register(() => this.CancelCall(messageId, operation)); flags |= RpcOperationFlags.CanCancel; } var frame = new LightweightRpcFrame(frameType, messageId, operation, flags, (uint)timeout, context?.Headers); var writeState = this.BeginWrite(frame); var writeTask = this.WriteRequestAsync(request, serializers.RequestSerializer, writeState); if (writeTask.IsCompletedSuccessfully) { if (timeout == 0 || RpcProxyOptions.RoundTripCancellationsAndTimeouts) { return(tcs.Task); } else { return(AwaitTimeoutResponse(tcs.Task, operation, timeout)); } } else { return(AwaitWrite(writeTask, tcs.Task)); } } catch (Exception ex) { this.HandleCallError(messageId, ex); throw; } async Task <TResponse> AwaitTimeoutResponse(Task <TResponse> responseTask, string operation, int timeout) { var completedTask = await Task.WhenAny(responseTask, Task.Delay(timeout)).ContextFree(); if (completedTask == responseTask) { return(responseTask.AwaiterResult()); } else { throw new TimeoutException($"Operation '{operation}' didn't complete within the timeout ({timeout} ms)."); } } async Task <TResponse> AwaitWrite(ValueTask writeTask, Task <TResponse> responseTask) { await writeTask.ContextFree(); if (timeout == 0 || RpcProxyOptions.RoundTripCancellationsAndTimeouts) { return(await responseTask.ContextFree()); } else { return(await AwaitTimeoutResponse(responseTask, operation, timeout).ContextFree()); } } }