private Task OnDispatch()

in src/Microsoft.ServiceFabric.Services.Remoting/V2/Runtime/ServiceRemotingMessageDispatcher.cs [176:258]


        private Task<IServiceRemotingResponseMessage> OnDispatch(
            IServiceRemotingRequestMessageHeader requestMessageHeaders,
            IServiceRemotingRequestMessageBody requestBody,
            CancellationToken cancellationToken)
        {
            if (!this.methodDispatcherMap.TryGetValue(requestMessageHeaders.InterfaceId, out var methodDispatcher))
            {
                throw new NotImplementedException(string.Format(
                    CultureInfo.CurrentCulture,
                    SR.ErrorInterfaceNotImplemented,
                    requestMessageHeaders.InterfaceId,
                    this.serviceImplementation));
            }

            Task<IServiceRemotingResponseMessageBody> dispatchTask = null;
            var stopwatch = Stopwatch.StartNew();

            var requestMessage = new ServiceRemotingRequestMessage(requestMessageHeaders, requestBody);
            ServiceRemotingServiceEvents.RaiseReceiveRequest(requestMessage, methodDispatcher.GetMethodName(requestMessageHeaders.MethodId));

            try
            {
                dispatchTask = methodDispatcher.DispatchAsync(
                    this.serviceImplementation,
                    requestMessageHeaders.MethodId,
                    requestBody,
                    this.GetRemotingMessageBodyFactory(),
                    cancellationToken);
            }
            catch (Exception e)
            {
                // Suggestion:
                // In future, we should consider consolodating how service remoting handles exceptions (failed requests) and normal responses (successful requests)
                // My contention is that a request that fails also generates a response (albeit a special kind) that encapsulates an exception.
                // If an IServiceRemotingResponseMessage can encapsulate a response in either case - this allows us to use response headers in either case for communication (think http 4XX / 5XX responses have standard headers)
                // The proxy on the caller side can always deserialize the exception and throw it, so user experience won't have to change due to this suggested architectural change.
                ServiceRemotingServiceEvents.RaiseExceptionResponse(e, requestMessage);

                var info = ExceptionDispatchInfo.Capture(e);
                this.servicePerformanceCounterProvider.OnServiceMethodFinish(
                    requestMessageHeaders.InterfaceId,
                    requestMessageHeaders.MethodId,
                    stopwatch.Elapsed,
                    e);
                info.Throw();
            }

            return dispatchTask.ContinueWith(
                t =>
                {
                    object responseBody = null;
                    try
                    {
                        responseBody = t.GetAwaiter().GetResult();
                    }
                    catch (Exception e)
                    {
                        ServiceRemotingServiceEvents.RaiseExceptionResponse(e, requestMessage);

                        var info = ExceptionDispatchInfo.Capture(e);

                        this.servicePerformanceCounterProvider.OnServiceMethodFinish(
                            requestMessageHeaders.InterfaceId,
                            requestMessageHeaders.MethodId,
                            stopwatch.Elapsed,
                            e);
                        info.Throw();
                    }

                    this.servicePerformanceCounterProvider.OnServiceMethodFinish(
                        requestMessageHeaders.InterfaceId,
                        requestMessageHeaders.MethodId,
                        stopwatch.Elapsed);

                    // We are creating empty response headers so that ServiceRemotingServiceEvents can add headers if they needed.
                    // This wont impact serialization cost since we check if its Empty , then dont serialize.
                    var response = new ServiceRemotingResponseMessage(new ServiceRemotingResponseMessageHeader(), (IServiceRemotingResponseMessageBody)responseBody);
                    ServiceRemotingServiceEvents.RaiseSendResponse(response, requestMessage);

                    return (IServiceRemotingResponseMessage)response;
                },
                TaskContinuationOptions.ExecuteSynchronously);
        }