Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
#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;
            }
        }
Ejemplo n.º 3
0
        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());
                }
            }
        }