internal static CosmosClientContext Create( CosmosClient cosmosClient, CosmosClientOptions clientOptions) { if (cosmosClient == null) { throw new ArgumentNullException(nameof(cosmosClient)); } clientOptions = ClientContextCore.CreateOrCloneClientOptions(clientOptions); HttpMessageHandler httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( clientOptions.GatewayModeMaxConnectionLimit, clientOptions.WebProxy); DocumentClient documentClient = new DocumentClient( cosmosClient.Endpoint, cosmosClient.AuthorizationTokenProvider, apitype: clientOptions.ApiType, sendingRequestEventArgs: clientOptions.SendingRequestEventArgs, transportClientHandlerFactory: clientOptions.TransportClientHandlerFactory, connectionPolicy: clientOptions.GetConnectionPolicy(), enableCpuMonitor: clientOptions.EnableCpuMonitor, storeClientFactory: clientOptions.StoreClientFactory, desiredConsistencyLevel: clientOptions.GetDocumentsConsistencyLevel(), handler: httpMessageHandler, sessionContainer: clientOptions.SessionContainer); return(ClientContextCore.Create( cosmosClient, documentClient, clientOptions)); }
public static CosmosHttpClient CreateWithConnectionPolicy( ApiType apiType, ICommunicationEventSource eventSource, ConnectionPolicy connectionPolicy, HttpMessageHandler httpMessageHandler, EventHandler <SendingRequestEventArgs> sendingRequestEventArgs, EventHandler <ReceivedResponseEventArgs> receivedResponseEventArgs) { if (connectionPolicy == null) { throw new ArgumentNullException(nameof(connectionPolicy)); } Func <HttpClient> httpClientFactory = connectionPolicy.HttpClientFactory; if (httpClientFactory != null) { if (sendingRequestEventArgs != null && receivedResponseEventArgs != null) { throw new InvalidOperationException($"{nameof(connectionPolicy.HttpClientFactory)} can not be set at the same time as {nameof(sendingRequestEventArgs)} or {nameof(ReceivedResponseEventArgs)}"); } HttpClient userHttpClient = httpClientFactory.Invoke() ?? throw new ArgumentNullException($"{nameof(httpClientFactory)} returned null. {nameof(httpClientFactory)} must return a HttpClient instance."); return(CosmosHttpClientCore.CreateHelper( httpClient: userHttpClient, httpMessageHandler: httpMessageHandler, requestTimeout: connectionPolicy.RequestTimeout, userAgentContainer: connectionPolicy.UserAgentContainer, apiType: apiType, eventSource: eventSource)); } if (httpMessageHandler == null) { httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( gatewayModeMaxConnectionLimit: connectionPolicy.MaxConnectionLimit, webProxy: null); } if (sendingRequestEventArgs != null || receivedResponseEventArgs != null) { httpMessageHandler = CosmosHttpClientCore.CreateHttpMessageHandler( httpMessageHandler, sendingRequestEventArgs, receivedResponseEventArgs); } HttpClient httpClient = new HttpClient(httpMessageHandler); return(CosmosHttpClientCore.CreateHelper( httpClient: httpClient, httpMessageHandler: httpMessageHandler, requestTimeout: connectionPolicy.RequestTimeout, userAgentContainer: connectionPolicy.UserAgentContainer, apiType: apiType, eventSource: eventSource)); }
public async Task DocumentClient_BuildHttpClientFactory_WithHandler() { HttpMessageHandler messageHandler = new CustomMessageHandler(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { HttpClientFactory = () => new HttpClient(messageHandler) }; CosmosHttpClient httpClient = CosmosHttpClientCore.CreateWithConnectionPolicy( apiType: ApiType.None, eventSource: DocumentClientEventSource.Instance, connectionPolicy: connectionPolicy, httpMessageHandler: null, sendingRequestEventArgs: null, receivedResponseEventArgs: null); Assert.IsNotNull(httpClient); HttpResponseMessage response = await httpClient.GetAsync( uri : new Uri("https://localhost"), additionalHeaders : new DictionaryNameValueCollection(), resourceType : ResourceType.Document, diagnosticsContext : null, cancellationToken : default);
private async Task <HttpResponseMessage> SendHttpHelperAsync( Func <ValueTask <HttpRequestMessage> > createRequestMessageAsync, ResourceType resourceType, HttpTimeoutPolicy timeoutPolicy, IClientSideRequestStatistics clientSideRequestStatistics, CancellationToken cancellationToken) { DateTime startDateTimeUtc = DateTime.UtcNow; IEnumerator <(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> timeoutEnumerator = timeoutPolicy.GetTimeoutEnumerator(); timeoutEnumerator.MoveNext(); while (true) { cancellationToken.ThrowIfCancellationRequested(); (TimeSpan requestTimeout, TimeSpan delayForNextRequest) = timeoutEnumerator.Current; using (HttpRequestMessage requestMessage = await createRequestMessageAsync()) { // If the default cancellation token is passed then use the timeout policy using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); cancellationTokenSource.CancelAfter(requestTimeout); DateTime requestStartTime = DateTime.UtcNow; try { HttpResponseMessage responseMessage = await this.ExecuteHttpHelperAsync( requestMessage, resourceType, cancellationTokenSource.Token); if (clientSideRequestStatistics is ClientSideRequestStatisticsTraceDatum datum) { datum.RecordHttpResponse(requestMessage, responseMessage, resourceType, requestStartTime); } if (!timeoutPolicy.ShouldRetryBasedOnResponse(requestMessage.Method, responseMessage)) { return(responseMessage); } bool isOutOfRetries = CosmosHttpClientCore.IsOutOfRetries(timeoutPolicy, startDateTimeUtc, timeoutEnumerator); if (isOutOfRetries) { return(responseMessage); } } catch (Exception e) { if (clientSideRequestStatistics is ClientSideRequestStatisticsTraceDatum datum) { datum.RecordHttpException(requestMessage, e, resourceType, requestStartTime); } bool isOutOfRetries = CosmosHttpClientCore.IsOutOfRetries(timeoutPolicy, startDateTimeUtc, timeoutEnumerator); switch (e) { case OperationCanceledException operationCanceledException: // Throw if the user passed in cancellation was requested if (cancellationToken.IsCancellationRequested) { throw; } // Convert OperationCanceledException to 408 when the HTTP client throws it. This makes it clear that the // the request timed out and was not user canceled operation. if (isOutOfRetries || !timeoutPolicy.IsSafeToRetry(requestMessage.Method)) { // throw current exception (caught in transport handler) string message = $"GatewayStoreClient Request Timeout. Start Time UTC:{startDateTimeUtc}; Total Duration:{(DateTime.UtcNow - startDateTimeUtc).TotalMilliseconds} Ms; Request Timeout {requestTimeout.TotalMilliseconds} Ms; Http Client Timeout:{this.httpClient.Timeout.TotalMilliseconds} Ms; Activity id: {System.Diagnostics.Trace.CorrelationManager.ActivityId};"; e.Data.Add("Message", message); throw; } break; case WebException webException: if (isOutOfRetries || (!timeoutPolicy.IsSafeToRetry(requestMessage.Method) && !WebExceptionUtility.IsWebExceptionRetriable(webException))) { throw; } break; case HttpRequestException httpRequestException: if (isOutOfRetries || !timeoutPolicy.IsSafeToRetry(requestMessage.Method)) { throw; } break; default: throw; } } } if (delayForNextRequest != TimeSpan.Zero) { await Task.Delay(delayForNextRequest); } } }