public override async Task <ResponseMessage> SendAsync(
            RequestMessage request,
            CancellationToken cancellationToken)
        {
            try
            {
                ResponseMessage response = await this.ProcessMessageAsync(request, cancellationToken);

                Debug.Assert(System.Diagnostics.Trace.CorrelationManager.ActivityId != Guid.Empty, "Trace activity id is missing");

                return(response);
            }
            //catch DocumentClientException and exceptions that inherit it. Other exception types happen before a backend request
            catch (DocumentClientException ex)
            {
                Debug.Assert(System.Diagnostics.Trace.CorrelationManager.ActivityId != Guid.Empty, "Trace activity id is missing");
                return(ex.ToCosmosResponseMessage(request));
            }
            catch (CosmosException ce)
            {
                Debug.Assert(System.Diagnostics.Trace.CorrelationManager.ActivityId != Guid.Empty, "Trace activity id is missing");
                return(ce.ToCosmosResponseMessage(request));
            }
            catch (OperationCanceledException ex)
            {
                // Catch Operation Cancelled Exception and convert to Timeout 408 if the user did not cancel it.
                // Throw the exception if the user cancelled.
                if (cancellationToken.IsCancellationRequested)
                {
                    throw;
                }

                Debug.Assert(System.Diagnostics.Trace.CorrelationManager.ActivityId != Guid.Empty, "Trace activity id is missing");
                CosmosException cosmosException = CosmosExceptionFactory.CreateRequestTimeoutException(
                    message: ex.Data?["Message"].ToString(),
                    headers: new Headers()
                {
                    ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString()
                },
                    innerException: ex,
                    trace: request.Trace);
                return(cosmosException.ToCosmosResponseMessage(request));
            }
            catch (AggregateException ex)
            {
                Debug.Assert(System.Diagnostics.Trace.CorrelationManager.ActivityId != Guid.Empty, "Trace activity id is missing");
                // TODO: because the SDK underneath this path uses ContinueWith or task.Result we need to catch AggregateExceptions here
                // in order to ensure that underlying DocumentClientExceptions get propagated up correctly. Once all ContinueWith and .Result
                // is removed this catch can be safely removed.
                ResponseMessage errorMessage = AggregateExceptionConverter(ex, request);
                if (errorMessage != null)
                {
                    return(errorMessage);
                }

                throw;
            }
        }
        internal static ResponseMessage AggregateExceptionConverter(AggregateException aggregateException, RequestMessage request)
        {
            AggregateException      innerExceptions    = aggregateException.Flatten();
            DocumentClientException docClientException = (DocumentClientException)innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is DocumentClientException);

            if (docClientException != null)
            {
                return(docClientException.ToCosmosResponseMessage(request));
            }

            Exception       exception       = innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is CosmosException);
            CosmosException cosmosException = exception as CosmosException;

            if (cosmosException != null)
            {
                return(cosmosException.ToCosmosResponseMessage(request));
            }

            return(null);
        }