예제 #1
0
        /// <summary>
        ///  DuplexStreaming メソッドを生成します。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="builderContext">コンテキスト</param>
        /// <returns>メソッド</returns>
        private DuplexStreamingServerMethod <TRequest, TResponse> CreateDuplexStreamingServerMethod <TRequest, TResponse>(MethodBuildContext builderContext)
            where TRequest : class where TResponse : class
        {
            DuplexStreamingServerMethod <TRequest, TResponse> method = builderContext.MethodImpl.CreateDelegate(typeof(DuplexStreamingServerMethod <TRequest, TResponse>), builderContext.ServiceInstance) as DuplexStreamingServerMethod <TRequest, TResponse>;

            GrpcServerPerformanceListener performanceListener = builderContext.NeedNotifyPerformanceLog ? builderContext.Settings.PerformanceListener : null;

            return(async delegate(IAsyncStreamReader <TRequest> requestStream, IServerStreamWriter <TResponse> responseStream, ServerCallContext context)
            {
                try
                {
                    await OnExecutingServiceMethodAsync(context, builderContext.InvokingInterceptors, performanceListener).ConfigureAwait(false);

                    if (performanceListener != null)
                    {
                        performanceListener.NotifyMethodCalling(context);
                    }

                    Stopwatch watch = Stopwatch.StartNew();
                    double elapsd;

                    try
                    {
                        await method(
                            new RequestStreamReader <TRequest>(requestStream, context, performanceListener)
                            , new ResponseStreamWriter <TResponse>(responseStream, context, performanceListener)
                            , context
                            ).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodFailed, context.Method) + ex.Message, ex, context);
                    }
                    finally
                    {
                        elapsd = GrpcPerformanceListener.GetMilliseconds(watch);
                        if (performanceListener != null)
                        {
                            performanceListener.NotifyMethodCalled(context, elapsd);
                        }
                    }

                    await OnExecutedServiceMethodAsync(context, builderContext.InvokedInterceptors, performanceListener).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Exception wrapped;
                    if (HandleException(context, builderContext.ExceptionHandlers, performanceListener, ex, out wrapped))
                    {
                        GrpcExceptionListener.NotifyCatchServerException(context, wrapped);
                        throw wrapped;
                    }
                    else
                    {
                        GrpcExceptionListener.NotifyCatchServerException(context, ex);
                        throw;
                    }
                }
            });
        }
예제 #2
0
        /// <summary>
        /// Unary メソッドを非同期で呼び出します。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="method">メソッド</param>
        /// <param name="host">ホスト</param>
        /// <param name="options">オプション</param>
        /// <param name="request">リクエスト</param>
        /// <returns>呼び出しオブジェクト</returns>
        public override AsyncUnaryCall <TResponse> AsyncUnaryCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request)
        {
            double elapsed = 0;

            try
            {
                method = GetCustomMethod <TRequest, TResponse>(method);

                OnInvokingMethod(method, host, options, request);

                Stopwatch watch = null;
                AsyncUnaryCall <TResponse> call;

                try
                {
                    watch = Stopwatch.StartNew();
                    call  = m_Invoker.AsyncUnaryCall(method, host, options, request);
                }
                finally
                {
                    elapsed = GrpcPerformanceListener.GetMilliseconds(watch);
                }

                OnInvokedMethod(method, host, options, request, elapsed);

                // 待機されると dispose が呼ばれず、解放されずに残ってしまう
                // ストリーム操作もないため、監視しない
                // return GrcpCallInvokerContext.Regist<TRequest, TResponse>(call, method, host, options);
                return(call);
            }
            catch (Exception ex)
            {
                GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex);

                Exception alternate;

                if (HandleException(method, host, options, ex, out alternate))
                {
                    throw alternate;
                }
                else
                {
                    throw;
                }
            }
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        async Task IClientStreamWriter <TRequest> .CompleteAsync()
        {
            Stopwatch watch = Stopwatch.StartNew();

            try
            {
                await m_Target.CompleteAsync().ConfigureAwait(false);
            }
            finally
            {
                GrpcPerformanceListener.GetMilliseconds(watch);
            }

            if (m_OnCompleted != null)
            {
                m_OnCompleted();
            }
        }
예제 #4
0
        /// <summary>
        /// Unary メソッドを呼び出します。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="method">メソッド</param>
        /// <param name="host">ホスト</param>
        /// <param name="options">オプション</param>
        /// <param name="request">リクエスト</param>
        /// <returns>レスポンス</returns>
        public override TResponse BlockingUnaryCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request)
        {
            double elapsed = 0;

            try
            {
                method = GetCustomMethod <TRequest, TResponse>(method);

                OnInvokingMethod(method, host, options, request);

                Stopwatch watch = null;

                TResponse result;

                try
                {
                    watch  = Stopwatch.StartNew();
                    result = m_Invoker.BlockingUnaryCall(method, host, options, request);
                }
                finally
                {
                    elapsed = GrpcPerformanceListener.GetMilliseconds(watch);
                }

                OnInvokedMethod(method, host, options, request, elapsed);

                return(result);
            }
            catch (Exception ex)
            {
                GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex);

                Exception alternate;

                if (HandleException(method, host, options, ex, out alternate))
                {
                    throw alternate;
                }
                else
                {
                    throw;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// ServerStreaming メソッドを非同期で呼び出します。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="method">メソッド</param>
        /// <param name="host">ホスト</param>
        /// <param name="options">オプション</param>
        /// <param name="request">リクエスト</param>
        /// <returns>呼び出しオブジェクト</returns>
        public override AsyncServerStreamingCall <TResponse> AsyncServerStreamingCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request)
        {
            double elapsed = 0;

            try
            {
                method = GetCustomMethod <TRequest, TResponse>(method);

                OnInvokingMethod(method, host, options, request);

                Stopwatch watch = null;
                AsyncServerStreamingCall <TResponse> call;

                try
                {
                    watch = Stopwatch.StartNew();
                    call  = m_Invoker.AsyncServerStreamingCall(method, host, options, request);
                }
                finally
                {
                    elapsed = GrpcPerformanceListener.GetMilliseconds(watch);
                }

                OnInvokedMethod(method, host, options, request, elapsed);

                return(GrpcCallInvokerContext.Regist <TRequest, TResponse>(call, method, host, options, m_Settings.PerformanceListener));
            }
            catch (Exception ex)
            {
                GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex);

                Exception alternate;

                if (HandleException(method, host, options, ex, out alternate))
                {
                    throw alternate;
                }
                else
                {
                    throw;
                }
            }
        }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        Task IAsyncStreamWriter <TResponse> .WriteAsync(TResponse message)
        {
            if (m_PerformanceListener != null)
            {
                m_PerformanceListener.NotifyResponseWriting(m_Context);
            }

            Stopwatch watch = Stopwatch.StartNew();

            try
            {
                return(m_Target.WriteAsync(message));
            }
            finally
            {
                if (m_PerformanceListener != null)
                {
                    m_PerformanceListener.NotifyResponseWrote(m_Context, GrpcPerformanceListener.GetMilliseconds(watch));
                }
            }
        }
예제 #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task <bool> IAsyncEnumerator <TRequest> .MoveNext(CancellationToken cancellationToken)
        {
            if (m_PerformanceListener != null)
            {
                m_PerformanceListener.NotifyRequestReading(m_Context);
            }

            Stopwatch watch = Stopwatch.StartNew();

            try
            {
                return(m_Target.MoveNext(cancellationToken));
            }
            finally
            {
                if (m_PerformanceListener != null)
                {
                    m_PerformanceListener.NotifyRequestReaded(m_Context, GrpcPerformanceListener.GetMilliseconds(watch));
                }
            }
        }
예제 #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        async Task <bool> IAsyncEnumerator <TResponse> .MoveNext(CancellationToken cancellationToken)
        {
            if (m_PerformanceListener != null)
            {
                m_PerformanceListener.NotifyResponseReading(m_Method, m_Host, m_Options);
            }

            Stopwatch watch = Stopwatch.StartNew();

            bool result;

            try
            {
                result = await m_Target.MoveNext(cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                if (m_PerformanceListener != null)
                {
                    m_PerformanceListener.NotifyResponseReaded(m_Method, m_Host, m_Options, GrpcPerformanceListener.GetMilliseconds(watch));
                }
            }

            if (!result && m_OnEndResponse != null)
            {
                m_OnEndResponse();
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serviceName"></param>
        /// <param name="methodName"></param>
        /// <param name="outputPerformanceLog"></param>
        /// <returns></returns>
        private Marshaller <T> GetMarshaller <T>(string serviceName, string methodName, bool outputPerformanceLog)
        {
            Marshaller <T> marshaller = m_Settings.GetMarshallerFactoryOrDefault().GetMarshaller <T>();

            if (!outputPerformanceLog)
            {
                return(marshaller);
            }

            string typeName = typeof(T).Name;

            return(new Marshaller <T>(

                       delegate(T arg)
            {
                try
                {
                    Stopwatch watch = Stopwatch.StartNew();
                    byte[] data = marshaller.Serializer(arg);

                    if (m_Settings.PerformanceListener != null)
                    {
                        m_Settings.PerformanceListener.NotifySerialized(serviceName, methodName, typeName, GrpcPerformanceListener.GetMilliseconds(watch), data == null ? 0 : data.Length);
                    }

                    return data;
                }
                catch (Exception ex)
                {
                    GrpcExceptionListener.NotifyCatchSerializerException(serviceName, methodName, typeof(T), ex);
                    throw new GrpcSerializerException(ex.Message, ex, serviceName, methodName, typeName);
                }
            }

                       , delegate(byte[] data)
            {
                try
                {
                    Stopwatch watch = Stopwatch.StartNew();
                    T arg = marshaller.Deserializer(data);

                    if (m_Settings.PerformanceListener != null)
                    {
                        m_Settings.PerformanceListener.NotifyDeserialized(serviceName, methodName, typeName, GrpcPerformanceListener.GetMilliseconds(watch), data == null ? 0 : data.Length);
                    }

                    return arg;
                }
                catch (Exception ex)
                {
                    GrpcExceptionListener.NotifyCatchSerializerException(serviceName, methodName, typeof(T), ex);
                    throw new GrpcSerializerException(ex.Message, ex, serviceName, methodName, typeName);
                }
            }

                       ));
        }
예제 #10
0
        /// <summary>
        /// 例外をキャッチしたときの処理を行います。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="method">メソッド</param>
        /// <param name="host">ホスト</param>
        /// <param name="options">オプション</param>
        /// <param name="original">キャッチした例外</param>
        /// <param name="alternate">代わりにスローさせる例外</param>
        /// <returns>処理された場合、true を返します。</returns>
        private bool HandleException <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, Exception original, out Exception alternate)
        {
            Exception alt = null;

            foreach (IGrpcClientMethodExceptionHandler interceptor in m_Settings.InvokingInterceptors)
            {
                if (interceptor == null)
                {
                    continue;
                }

                Stopwatch watch = Stopwatch.StartNew();

                try
                {
                    bool wrapped = interceptor.ReplaceException(method, host, options, original, out alt);

                    if (m_Settings.PerformanceListener != null)
                    {
                        m_Settings.PerformanceListener.NotifyMethodIntercepted(method, host, options, interceptor, GrpcPerformanceListener.GetMilliseconds(watch));
                    }

                    if (wrapped)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex);
                    throw new GrpcClientMethodException(string.Format(Properties.MessageResources.ClientMethodInterceptorFailed + ex.Message, method.FullName, interceptor.Name), ex, method, host, options, interceptor);
                }
            }

            if (alt != null && !object.Equals(alt, original))
            {
                alternate = alt;
                return(true);
            }
            else
            {
                alternate = null;
                return(false);
            }
        }
예제 #11
0
        /// <summary>
        /// メソッドが実行されたときの処理を行います。
        /// </summary>
        /// <typeparam name="TRequest">リクエストの型</typeparam>
        /// <typeparam name="TResponse">レスポンスの型</typeparam>
        /// <param name="method">メソッド</param>
        /// <param name="host">ホスト</param>
        /// <param name="options">オプション</param>
        /// <param name="request">リクエスト</param>
        /// <param name="elapsedMilliseconds">処理時間(ミリ秒)</param>
        protected virtual void OnInvokedMethod <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request, double elapsedMilliseconds)
        {
            if (m_Settings.PerformanceListener != null)
            {
                m_Settings.PerformanceListener.NotifyMethodCalled(method, host, options, elapsedMilliseconds);
            }

            foreach (IGrpcClientMethodInvokedInterceptor interceptor in m_Settings.InvokingInterceptors)
            {
                if (interceptor == null)
                {
                    continue;
                }

                Stopwatch watch = Stopwatch.StartNew();

                try
                {
                    interceptor.OnInvoked(method, host, options);

                    if (m_Settings.PerformanceListener != null)
                    {
                        m_Settings.PerformanceListener.NotifyMethodIntercepted(method, host, options, interceptor, GrpcPerformanceListener.GetMilliseconds(watch));
                    }
                }
                catch (Exception ex)
                {
                    throw new GrpcClientMethodException(string.Format(Properties.MessageResources.ClientMethodInterceptorFailed + ex.Message, method.FullName, interceptor.Name), ex, method, host, options, interceptor);
                }
            }
        }
예제 #12
0
        /// <summary>
        /// 例外を処理します。
        /// </summary>
        /// <param name="context">コンテキスト</param>
        /// <param name="exceptionHandlers">例外ハンドラ</param>
        /// <param name="performanceListener">パフォーマンスリスナー</param>
        /// <param name="original">発生した例外</param>
        /// <param name="alternate">代わりにスローする例外</param>
        /// <returns>例外がラップされた場合、true を返します。</returns>
        private bool HandleException(ServerCallContext context, IEnumerable <IGrpcServerMethodExceptionHandler> exceptionHandlers, GrpcServerPerformanceListener performanceListener, Exception original, out Exception alternate)
        {
            Exception alt = null;

            if (exceptionHandlers != null)
            {
                foreach (IGrpcServerMethodExceptionHandler handler in exceptionHandlers)
                {
                    if (handler == null)
                    {
                        continue;
                    }

                    Stopwatch watch = Stopwatch.StartNew();

                    try
                    {
                        if (handler.RelpaceException(context, original, out alt))
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodInterceptorFailed + ex.Message, context.Method, handler.Name), ex, context, handler);
                    }
                    finally
                    {
                        if (performanceListener != null)
                        {
                            performanceListener.NotifyMethodIntercepted(context, handler, GrpcPerformanceListener.GetMilliseconds(watch));
                        }
                    }
                }
            }

            if (alt == null)
            {
                alt = original;
            }

            RpcException rpc = alt as RpcException;

            if (rpc == null)
            {
                alternate = CreateRpcException(context, alt);
            }
            else
            {
                alternate = rpc;
            }

            return(!object.Equals(original, alternate));
        }
예제 #13
0
        /// <summary>
        /// サービスメソッドが呼び出されたときの処理を行います。
        /// </summary>
        /// <param name="context">コンテキスト</param>
        /// <param name="interceptors">割込処理</param>
        /// <param name="performanceListener">パフォーマンスリスナー</param>
        /// <returns></returns>
        private async Task OnExecutedServiceMethodAsync(ServerCallContext context, IEnumerable <IGrpcServerMethodInvokedInterceptor> interceptors, GrpcServerPerformanceListener performanceListener)
        {
            if (interceptors != null)
            {
                foreach (IGrpcServerMethodInvokedInterceptor interceptor in interceptors)
                {
                    if (interceptor == null)
                    {
                        continue;
                    }

                    Stopwatch watch = Stopwatch.StartNew();

                    try
                    {
                        await interceptor.OnInvokedAsync(context).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodInterceptorFailed + ex.Message, context.Method, interceptor.Name), ex, context, interceptor);
                    }
                    finally
                    {
                        if (performanceListener != null)
                        {
                            performanceListener.NotifyMethodIntercepted(context, interceptor, GrpcPerformanceListener.GetMilliseconds(watch));
                        }
                    }
                }
            }
        }
예제 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        async Task IAsyncStreamWriter <TRequest> .WriteAsync(TRequest message)
        {
            if (m_PerformanceListener != null)
            {
                m_PerformanceListener.NotifyRequestWriting(m_Method, m_Host, m_Options);
            }

            Stopwatch watch = Stopwatch.StartNew();

            try
            {
                await m_Target.WriteAsync(message).ConfigureAwait(false);
            }
            finally
            {
                if (m_PerformanceListener != null)
                {
                    m_PerformanceListener.NotifyRequestWrote(m_Method, m_Host, m_Options, GrpcPerformanceListener.GetMilliseconds(watch));
                }
            }
        }