private async Task <ShouldRetryResult> ShouldRetryInternalAsync(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            CancellationToken cancellationToken)
        {
            if (statusCode == HttpStatusCode.Gone)
            {
                if (subStatusCode == SubStatusCodes.PartitionKeyRangeGone ||
                    subStatusCode == SubStatusCodes.CompletingSplit ||
                    subStatusCode == SubStatusCodes.CompletingPartitionMigration)
                {
                    PartitionKeyRangeCache partitionKeyRangeCache = await this.container.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync();

                    string containerRid = await this.container.GetCachedRIDAsync(forceRefresh : false, cancellationToken : cancellationToken);

                    await partitionKeyRangeCache.TryGetOverlappingRangesAsync(containerRid, FeedRangeEpk.FullRange.Range, forceRefresh : true);

                    return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                }

                if (subStatusCode == SubStatusCodes.NameCacheIsStale)
                {
                    return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                }
            }

            return(null);
        }
        private Task <ShouldRetryResult> ShouldRetryAsyncInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName,
            Func <Task <ShouldRetryResult> > continueIfNotHandled)
        {
            if (!statusCode.HasValue &&
                !subStatusCode.HasValue)
            {
                return(continueIfNotHandled());
            }

            if (statusCode == HttpStatusCode.Gone &&
                subStatusCode == SubStatusCodes.NameCacheIsStale)
            {
                if (!string.IsNullOrEmpty(resourceIdOrFullName))
                {
                    this.clientCollectionCache.Refresh(resourceIdOrFullName);
                }

                return(Task.FromResult(ShouldRetryResult.NoRetry(new NotFoundException())));
            }

            return(continueIfNotHandled());
        }
Exemple #3
0
        private async Task <ShouldRetryResult> ShouldRetryInternalAsync(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            ShouldRetryResult shouldRetryResult,
            CancellationToken cancellationToken)
        {
            if (this.request == null)
            {
                // someone didn't call OnBeforeSendRequest - nothing we can do
                DefaultTrace.TraceCritical("Cannot apply RenameCollectionAwareClientRetryPolicy as OnBeforeSendRequest has not been called and there is no DocumentServiceRequest context.");
                return(shouldRetryResult);
            }

            Debug.Assert(shouldRetryResult != null);
            if (!shouldRetryResult.ShouldRetry && !this.hasTriggered && statusCode.HasValue && subStatusCode.HasValue)
            {
                if (this.request.IsNameBased &&
                    statusCode.Value == HttpStatusCode.NotFound &&
                    subStatusCode.Value == SubStatusCodes.ReadSessionNotAvailable)
                {
                    // Clear the session token, because the collection name might be reused.
                    DefaultTrace.TraceWarning("Clear the the token for named base request {0}", request.ResourceAddress);

                    this.sessionContainer.ClearTokenByCollectionFullname(request.ResourceAddress);

                    this.hasTriggered = true;

                    string oldCollectionRid = request.RequestContext.ResolvedCollectionRid;

                    request.ForceNameCacheRefresh = true;
                    request.RequestContext.ResolvedCollectionRid = null;

                    try
                    {
                        CosmosContainerProperties collectionInfo = await this.collectionCache.ResolveCollectionAsync(request, cancellationToken);

                        if (collectionInfo == null)
                        {
                            DefaultTrace.TraceCritical("Can't recover from session unavailable exception because resolving collection name {0} returned null", request.ResourceAddress);
                        }
                        else if (!string.IsNullOrEmpty(oldCollectionRid) && !string.IsNullOrEmpty(collectionInfo.ResourceId))
                        {
                            if (!oldCollectionRid.Equals(collectionInfo.ResourceId))
                            {
                                return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // When ResolveCollectionAsync throws an exception ignore it because it's an attempt to recover an existing
                        // error. When the recovery fails we return ShouldRetryResult.NoRetry and propaganate the original exception to the client

                        DefaultTrace.TraceCritical("Can't recover from session unavailable exception because resolving collection name {0} failed with {1}", request.ResourceAddress, e.ToString());
                    }
                }
            }

            return(shouldRetryResult);
        }
Exemple #4
0
        private ShouldRetryResult ShouldRetryInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName)
        {
            if (!statusCode.HasValue &&
                (!subStatusCode.HasValue ||
                 subStatusCode.Value == SubStatusCodes.Unknown))
            {
                return(null);
            }

            if (statusCode == HttpStatusCode.Gone &&
                subStatusCode == SubStatusCodes.NameCacheIsStale)
            {
                if (!this.retried)
                {
                    if (!string.IsNullOrEmpty(resourceIdOrFullName))
                    {
                        this.clientCollectionCache.Refresh(resourceIdOrFullName);
                    }

                    this.retried = true;
                    return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                }
                else
                {
                    return(ShouldRetryResult.NoRetry());
                }
            }

            return(null);
        }
Exemple #5
0
        private async Task <ResponseMessage> ReadNextInternalAsync(
            CosmosDiagnosticsContext diagnostics,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            Stream        stream    = null;
            OperationType operation = OperationType.ReadFeed;

            if (this.querySpec != null)
            {
                stream    = this.clientContext.SerializerCore.ToStreamSqlQuerySpec(this.querySpec, this.resourceType);
                operation = OperationType.Query;
            }

            ResponseMessage responseMessage = await this.clientContext.ProcessResourceOperationStreamAsync(
                resourceUri : this.containerCore.LinkUri,
                resourceType : this.resourceType,
                operationType : operation,
                requestOptions : this.queryRequestOptions,
                cosmosContainerCore : this.containerCore,
                partitionKey : this.queryRequestOptions?.PartitionKey,
                streamPayload : stream,
                requestEnricher : request =>
            {
                FeedRangeVisitor feedRangeVisitor = new FeedRangeVisitor(request);
                this.FeedRangeInternal.Accept(feedRangeVisitor);
                this.FeedRangeContinuation.Accept(feedRangeVisitor, QueryRequestOptions.FillContinuationToken);
                if (this.querySpec != null)
                {
                    request.Headers.Add(HttpConstants.HttpHeaders.ContentType, MediaTypes.QueryJson);
                    request.Headers.Add(HttpConstants.HttpHeaders.IsQuery, bool.TrueString);
                }
            },
                diagnosticsContext : diagnostics,
                cancellationToken : cancellationToken);

            ShouldRetryResult shouldRetryOnSplit = await this.FeedRangeContinuation.HandleSplitAsync(this.containerCore, responseMessage, cancellationToken);

            if (shouldRetryOnSplit.ShouldRetry)
            {
                return(await this.ReadNextInternalAsync(diagnostics, cancellationToken));
            }

            if (responseMessage.Content != null)
            {
                await CosmosElementSerializer.RewriteStreamAsTextAsync(responseMessage, this.queryRequestOptions);
            }

            if (responseMessage.IsSuccessStatusCode)
            {
                this.FeedRangeContinuation.ReplaceContinuation(responseMessage.Headers.ContinuationToken);
                this.hasMoreResultsInternal = !this.FeedRangeContinuation.IsDone;
                return(FeedRangeResponse.CreateSuccess(responseMessage, this.FeedRangeContinuation));
            }
            else
            {
                this.hasMoreResultsInternal = false;
                return(FeedRangeResponse.CreateFailure(responseMessage));
            }
        }
        private ShouldRetryResult ShouldRetryInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName)
        {
            if (!statusCode.HasValue &&
                (!subStatusCode.HasValue ||
                 subStatusCode.Value == SubStatusCodes.Unknown))
            {
                return(null);
            }

            if (statusCode == HttpStatusCode.BadRequest &&
                subStatusCode == SubStatusCodes.PartitionKeyMismatch &&
                this.retriesAttempted < MaxRetries)
            {
                Debug.Assert(resourceIdOrFullName != null);

                if (!string.IsNullOrEmpty(resourceIdOrFullName))
                {
                    this.clientCollectionCache.Refresh(resourceIdOrFullName, HttpConstants.Versions.CurrentVersion);
                }

                this.retriesAttempted++;

                return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
            }

            return(null);
        }
        private ShouldRetryResult ShouldRetryInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName)
        {
            if (!statusCode.HasValue &&
                (!subStatusCode.HasValue ||
                 subStatusCode.Value == SubStatusCodes.Unknown))
            {
                return(null);
            }

            if (statusCode == HttpStatusCode.Gone &&
                subStatusCode == SubStatusCodes.NameCacheIsStale)
            {
                if (!string.IsNullOrEmpty(resourceIdOrFullName))
                {
                    this.clientCollectionCache.Refresh(resourceIdOrFullName);
                }

                return(ShouldRetryResult.NoRetry(new NotFoundException()));
            }

            return(null);
        }
        private Task <ShouldRetryResult> ShouldRetryAsyncInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName,
            Func <Task <ShouldRetryResult> > continueIfNotHandled)
        {
            if (!statusCode.HasValue &&
                !subStatusCode.HasValue)
            {
                return(continueIfNotHandled());
            }

            if (statusCode == HttpStatusCode.BadRequest &&
                subStatusCode == SubStatusCodes.PartitionKeyMismatch &&
                this.retriesAttempted < MaxRetries)
            {
                Debug.Assert(resourceIdOrFullName != null);

                if (!string.IsNullOrEmpty(resourceIdOrFullName))
                {
                    this.clientCollectionCache.Refresh(resourceIdOrFullName);
                }

                this.retriesAttempted++;

                return(Task.FromResult(ShouldRetryResult.RetryAfter(TimeSpan.Zero)));
            }

            return(continueIfNotHandled());
        }
        public async Task RetriesOnWebException()
        {
            HttpMethod httpMethod = HttpMethod.Get;

            HttpRequestMessage httpRequestMessageFunc() => new HttpRequestMessage(httpMethod, "https://localhost:8081");

            IRetryPolicy retryPolicy = new TransientHttpClientRetryPolicy(
                httpRequestMessageFunc,
                TimeSpan.FromSeconds(10),
                new CosmosDiagnosticsContextCore());

            List <HttpMethod> httpMethods = new List <HttpMethod>()
            {
                HttpMethod.Get,
                HttpMethod.Delete,
                HttpMethod.Patch,
                HttpMethod.Post,
                HttpMethod.Put
            };

            foreach (HttpMethod method in httpMethods)
            {
                httpMethod = method;
                ShouldRetryResult shouldRetryResult = await retryPolicy.ShouldRetryAsync(new WebException("Test", WebExceptionStatus.ConnectFailure), default(CancellationToken));

                Assert.IsTrue(shouldRetryResult.ShouldRetry, method.ToString());
            }
        }
        /// <summary>
        /// Should the caller retry the operation.
        /// </summary>
        /// <param name="exception">Exception that occured when the operation was tried</param>
        /// <param name="cancellationToken"></param>
        /// <returns>True indicates caller should retry, False otherwise</returns>
        public Task <ShouldRetryResult> ShouldRetryAsync(
            Exception exception,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (exception is DocumentClientException)
            {
                DocumentClientException dce = (DocumentClientException)exception;
                if (!this.IsValidThrottleStatusCode(dce.StatusCode))
                {
                    DefaultTrace.TraceError(
                        "Operation will NOT be retried. Current attempt {0}, Status Code: {1} ",
                        this.currentAttemptCount,
                        dce.StatusCode);
                    return(Task.FromResult(ShouldRetryResult.NoRetry()));
                }

                return(this.ShouldRetryInternalAsync(dce.RetryAfter));
            }

            DefaultTrace.TraceError(
                "Operation will NOT be retried. Current attempt {0}, Exception: {1} ",
                this.currentAttemptCount,
                this.GetExceptionMessage(exception));
            return(Task.FromResult(ShouldRetryResult.NoRetry()));
        }
Exemple #11
0
        private ShouldRetryResult ShouldRetryInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            ShouldRetryResult shouldRetryResult)
        {
            if (this.request == null)
            {
                // someone didn't call OnBeforeSendRequest - nothing we can do
                return(shouldRetryResult);
            }

            if (!shouldRetryResult.ShouldRetry && !this.hasTriggered && statusCode.HasValue && subStatusCode.HasValue)
            {
                if (this.request.IsNameBased &&
                    statusCode.Value == HttpStatusCode.NotFound &&
                    subStatusCode.Value == SubStatusCodes.ReadSessionNotAvailable)
                {
                    // Clear the session token, because the collection name might be reused.
                    DefaultTrace.TraceWarning("Clear the the token for named base request {0}", request.ResourceAddress);

                    this.sessionContainer.ClearTokenByCollectionFullname(request.ResourceAddress);

                    this.hasTriggered = true;
                }
            }

            return(shouldRetryResult);
        }
        /// <summary>
        /// Should the caller retry the operation.
        /// </summary>
        /// <param name="exception">Exception that occurred when the operation was tried</param>
        /// <param name="cancellationToken"></param>
        /// <returns>True indicates caller should retry, False otherwise</returns>
        public async Task <ShouldRetryResult> ShouldRetryAsync(
            Exception exception,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            this.retryContext = null;
            // Received Connection error (HttpRequestException), initiate the endpoint rediscovery
            if (exception is HttpRequestException _)
            {
                DefaultTrace.TraceWarning("Endpoint not reachable. Refresh cache and retry");
                return(await this.ShouldRetryOnEndpointFailureAsync(
                           isReadRequest : this.isReadRequest,
                           forceRefresh : false,
                           retryOnPreferredLocations : true));
            }

            DocumentClientException clientException   = exception as DocumentClientException;
            ShouldRetryResult       shouldRetryResult = await this.ShouldRetryInternalAsync(
                clientException?.StatusCode,
                clientException?.GetSubStatus());

            if (shouldRetryResult != null)
            {
                return(shouldRetryResult);
            }

            return(await this.throttlingRetry.ShouldRetryAsync(exception, cancellationToken));
        }
        public async Task PartitionKeyRangeGoneRetryPolicyWithNextRetryPolicy()
        {
            Mock <IDocumentClientRetryPolicy> nextRetryPolicyMock = new Mock <IDocumentClientRetryPolicy>();

            nextRetryPolicyMock
            .Setup(m => m.ShouldRetryAsync(It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult <ShouldRetryResult>(ShouldRetryResult.RetryAfter(TimeSpan.FromDays(1))))
            .Verifiable();

            nextRetryPolicyMock
            .Setup(m => m.ShouldRetryAsync(It.IsAny <Exception>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult <ShouldRetryResult>(ShouldRetryResult.RetryAfter(TimeSpan.FromDays(1))))
            .Verifiable();

            PartitionKeyRangeGoneRetryPolicy retryPolicy = new PartitionKeyRangeGoneRetryPolicy(null, null, null, nextRetryPolicyMock.Object);

            ShouldRetryResult exceptionResult = await retryPolicy.ShouldRetryAsync(new Exception("", null), CancellationToken.None);

            Assert.IsNotNull(exceptionResult);
            Assert.IsTrue(exceptionResult.ShouldRetry);
            Assert.AreEqual(TimeSpan.FromDays(1), exceptionResult.BackoffTime);

            ShouldRetryResult messageResult = await retryPolicy.ShouldRetryAsync(new ResponseMessage(), CancellationToken.None);

            Assert.IsNotNull(exceptionResult);
            Assert.IsTrue(exceptionResult.ShouldRetry);
            Assert.AreEqual(TimeSpan.FromDays(1), exceptionResult.BackoffTime);
        }
Exemple #14
0
        /// <summary>
        /// Should the caller retry the operation.
        /// </summary>
        /// <param name="exception">Exception that occurred when the operation was tried</param>
        /// <param name="cancellationToken"></param>
        /// <returns>True indicates caller should retry, False otherwise</returns>
        public async Task <ShouldRetryResult> ShouldRetryAsync(
            Exception exception,
            CancellationToken cancellationToken)
        {
            this.retryContext = null;
            // Received Connection error (HttpRequestException), initiate the endpoint rediscovery
            if (exception is HttpRequestException _)
            {
                DefaultTrace.TraceWarning("ClientRetryPolicy: Gateway HttpRequestException Endpoint not reachable. Failed Location: {0}; ResourceAddress: {1}",
                                          this.documentServiceRequest?.RequestContext?.LocationEndpointToRoute?.ToString() ?? string.Empty,
                                          this.documentServiceRequest?.ResourceAddress ?? string.Empty);

                // Mark both read and write requests because it gateway exception.
                // This means all requests going to the region will fail.
                return(await this.ShouldRetryOnEndpointFailureAsync(
                           isReadRequest : this.isReadRequest,
                           markBothReadAndWriteAsUnavailable : true,
                           forceRefresh : false,
                           retryOnPreferredLocations : true));
            }

            if (exception is DocumentClientException clientException)
            {
                ShouldRetryResult shouldRetryResult = await this.ShouldRetryInternalAsync(
                    clientException?.StatusCode,
                    clientException?.GetSubStatus());

                if (shouldRetryResult != null)
                {
                    return(shouldRetryResult);
                }
            }

            return(await this.throttlingRetry.ShouldRetryAsync(exception, cancellationToken));
        }
        public Task <ShouldRetryResult> ShouldRetryAsync(
            Exception exception,
            CancellationToken cancellationToken)
        {
            TimeSpan backoffTime = TimeSpan.FromSeconds(0);

            if (!WebExceptionUtility.IsWebExceptionRetriable(exception))
            {
                // Have caller propagate original exception.
                this.durationTimer.Stop();
                return(Task.FromResult(ShouldRetryResult.NoRetry()));
            }

            // Don't penalise first retry with delay.
            if (attemptCount++ > 1)
            {
                int remainingSeconds = WebExceptionRetryPolicy.waitTimeInSeconds - this.durationTimer.Elapsed.Seconds;
                if (remainingSeconds <= 0)
                {
                    this.durationTimer.Stop();
                    return(Task.FromResult(ShouldRetryResult.NoRetry()));
                }

                backoffTime = TimeSpan.FromSeconds(Math.Min(this.currentBackoffSeconds, remainingSeconds));
                this.currentBackoffSeconds *= WebExceptionRetryPolicy.backoffMultiplier;
            }

            DefaultTrace.TraceWarning("Received retriable web exception, will retry, {0}", exception);

            return(Task.FromResult(ShouldRetryResult.RetryAfter(backoffTime)));
        }
        private Task <ShouldRetryResult> ShouldRetryAsyncInternal(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode,
            string resourceIdOrFullName,
            Func <Task <ShouldRetryResult> > continueIfNotHandled)
        {
            if (statusCode.HasValue &&
                subStatusCode.HasValue &&
                statusCode == HttpStatusCode.Gone &&
                subStatusCode == SubStatusCodes.NameCacheIsStale)
            {
                if (!this.retried)
                {
                    if (!string.IsNullOrEmpty(resourceIdOrFullName))
                    {
                        this.clientCollectionCache.Refresh(resourceIdOrFullName);
                    }

                    this.retried = true;
                    return(Task.FromResult(ShouldRetryResult.RetryAfter(TimeSpan.Zero)));
                }
                else
                {
                    return(Task.FromResult(ShouldRetryResult.NoRetry()));
                }
            }

            return(continueIfNotHandled != null?continueIfNotHandled() : Task.FromResult(ShouldRetryResult.NoRetry()));
        }
        private async Task <ShouldRetryResult> ShouldRetryOnEndpointFailureAsync(
            bool isReadRequest,
            bool forceRefresh,
            bool retryOnPreferredLocations)
        {
            if (!this.enableEndpointDiscovery || this.failoverRetryCount > MaxRetryCount)
            {
                DefaultTrace.TraceInformation("ShouldRetryOnEndpointFailureAsync() Not retrying. Retry count = {0}", this.failoverRetryCount);
                return(ShouldRetryResult.NoRetry());
            }

            this.failoverRetryCount++;

            if (this.locationEndpoint != null)
            {
                if (isReadRequest)
                {
                    this.globalEndpointManager.MarkEndpointUnavailableForRead(this.locationEndpoint);
                }
                else
                {
                    this.globalEndpointManager.MarkEndpointUnavailableForWrite(this.locationEndpoint);
                }
            }

            TimeSpan retryDelay = TimeSpan.Zero;

            if (!isReadRequest)
            {
                DefaultTrace.TraceInformation("Failover happening. retryCount {0}", this.failoverRetryCount);

                if (this.failoverRetryCount > 1)
                {
                    //if retried both endpoints, follow regular retry interval.
                    retryDelay = TimeSpan.FromMilliseconds(ClientRetryPolicy.RetryIntervalInMS);
                }
            }
            else
            {
                retryDelay = TimeSpan.FromMilliseconds(ClientRetryPolicy.RetryIntervalInMS);
            }

            await this.globalEndpointManager.RefreshLocationAsync(null, forceRefresh);

            int retryLocationIndex = this.failoverRetryCount; // Used to generate a round-robin effect

            if (retryOnPreferredLocations)
            {
                retryLocationIndex = 0; // When the endpoint is marked as unavailable, it is moved to the bottom of the preferrence list
            }

            this.retryContext = new RetryContext
            {
                RetryLocationIndex = retryLocationIndex,
                RetryRequestOnPreferredLocations = retryOnPreferredLocations,
            };

            return(ShouldRetryResult.RetryAfter(retryDelay));
        }
        private async Task <ShouldRetryResult> ShouldRetryInternalAsync(
            HttpStatusCode?statusCode,
            SubStatusCodes?subStatusCode)
        {
            if (!statusCode.HasValue &&
                (!subStatusCode.HasValue ||
                 subStatusCode.Value == SubStatusCodes.Unknown))
            {
                return(null);
            }

            // Received 403.3 on write region, initiate the endpoint rediscovery
            if (statusCode == HttpStatusCode.Forbidden &&
                subStatusCode == SubStatusCodes.WriteForbidden)
            {
                if (this.partitionKeyRangeLocationCache.TryMarkEndpointUnavailableForPartitionKeyRange(
                        this.documentServiceRequest))
                {
                    return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                }

                DefaultTrace.TraceWarning("Endpoint not writable. Refresh cache and retry");
                return(await this.ShouldRetryOnEndpointFailureAsync(
                           isReadRequest : false,
                           forceRefresh : true,
                           retryOnPreferredLocations : false));
            }

            // Regional endpoint is not available yet for reads (e.g. add/ online of region is in progress)
            if (statusCode == HttpStatusCode.Forbidden &&
                subStatusCode == SubStatusCodes.DatabaseAccountNotFound &&
                (this.isReadRequest || this.canUseMultipleWriteLocations))
            {
                DefaultTrace.TraceWarning("Endpoint not available for reads. Refresh cache and retry");
                return(await this.ShouldRetryOnEndpointFailureAsync(
                           isReadRequest : this.isReadRequest,
                           forceRefresh : false,
                           retryOnPreferredLocations : false));
            }

            if (statusCode == HttpStatusCode.NotFound &&
                subStatusCode == SubStatusCodes.ReadSessionNotAvailable)
            {
                return(this.ShouldRetryOnSessionNotAvailable());
            }

            // Received 503.0 due to client connect timeout or Gateway
            if (statusCode == HttpStatusCode.ServiceUnavailable &&
                subStatusCode == SubStatusCodes.Unknown)
            {
                this.partitionKeyRangeLocationCache.TryMarkEndpointUnavailableForPartitionKeyRange(
                    this.documentServiceRequest);

                return(this.ShouldRetryOnServiceUnavailable());
            }

            return(null);
        }
Exemple #19
0
        public async Task ShouldRetry_NoPolicy()
        {
            BatchOperationResult result    = new BatchOperationResult(HttpStatusCode.OK);
            ItemBatchOperation   operation = new ItemBatchOperation(OperationType.Create, 0);

            operation.AttachContext(new ItemBatchOperationContext(string.Empty));
            ShouldRetryResult shouldRetryResult = await operation.Context.ShouldRetryAsync(result, default(CancellationToken));

            Assert.IsFalse(shouldRetryResult.ShouldRetry);
        }
Exemple #20
0
        public async Task RetriesOn429()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                new ResourceThrottleRetryPolicy(1));

            BatchOperationResult result            = new BatchOperationResult((HttpStatusCode)StatusCodes.TooManyRequests);
            ShouldRetryResult    shouldRetryResult = await retryPolicy.ShouldRetryAsync(result.ToResponseMessage(), default(CancellationToken));

            Assert.IsTrue(shouldRetryResult.ShouldRetry);
        }
Exemple #21
0
        public async Task ShouldRetry_NoPolicy()
        {
            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(HttpStatusCode.OK);
            ItemBatchOperation operation             = new ItemBatchOperation(OperationType.Create, 0, Cosmos.PartitionKey.Null);

            operation.AttachContext(new ItemBatchOperationContext(string.Empty));
            ShouldRetryResult shouldRetryResult = await operation.Context.ShouldRetryAsync(result, default);

            Assert.IsFalse(shouldRetryResult.ShouldRetry);
        }
Exemple #22
0
        public async Task NotRetryOnSuccess()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                new ResourceThrottleRetryPolicy(1));

            BatchOperationResult result            = new BatchOperationResult(HttpStatusCode.OK);
            ShouldRetryResult    shouldRetryResult = await retryPolicy.ShouldRetryAsync(result.ToResponseMessage(), default(CancellationToken));

            Assert.IsFalse(shouldRetryResult.ShouldRetry);
        }
Exemple #23
0
        private ShouldRetryResult ShouldRetryOnSessionNotAvailable()
        {
            this.sessionTokenRetryCount++;

            if (!this.enableEndpointDiscovery)
            {
                // if endpoint discovery is disabled, the request cannot be retried anywhere else
                return(ShouldRetryResult.NoRetry());
            }
            else
            {
                if (this.canUseMultipleWriteLocations)
                {
                    ReadOnlyCollection <Uri> endpoints = this.isReadRequest ? this.globalEndpointManager.ReadEndpoints : this.globalEndpointManager.WriteEndpoints;

                    if (this.sessionTokenRetryCount > endpoints.Count)
                    {
                        // When use multiple write locations is true and the request has been tried
                        // on all locations, then don't retry the request
                        return(ShouldRetryResult.NoRetry());
                    }
                    else
                    {
                        this.retryContext = new RetryContext()
                        {
                            RetryCount = this.sessionTokenRetryCount - 1,
                            RetryRequestOnPreferredLocations       = this.sessionTokenRetryCount > 1,
                            ClearSessionTokenOnSessionNotAvailable = (this.sessionTokenRetryCount == endpoints.Count) // clear on last attempt
                        };

                        return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                    }
                }
                else
                {
                    if (this.sessionTokenRetryCount > 1)
                    {
                        // When cannot use multiple write locations, then don't retry the request if
                        // we have already tried this request on the write location
                        return(ShouldRetryResult.NoRetry());
                    }
                    else
                    {
                        this.retryContext = new RetryContext
                        {
                            RetryCount = this.sessionTokenRetryCount - 1,
                            RetryRequestOnPreferredLocations       = false,
                            ClearSessionTokenOnSessionNotAvailable = true,
                        };

                        return(ShouldRetryResult.RetryAfter(TimeSpan.Zero));
                    }
                }
            }
        }
Exemple #24
0
        // Extracted partition key might be invalid as CollectionCache might be stale.
        // Stale collection cache is refreshed through PartitionKeyMismatchRetryPolicy
        // and partition-key is extracted again.
        internal async Task <ResponseMessage> ExtractPartitionKeyAndProcessItemStreamAsync <T>(
            PartitionKey?partitionKey,
            string itemId,
            T item,
            OperationType operationType,
            RequestOptions requestOptions,
            CancellationToken cancellationToken)
        {
            Stream streamPayload = this.ClientContext.SerializerCore.ToStream <T>(item);

            // User specified PK value, no need to extract it
            if (partitionKey.HasValue)
            {
                return(await this.ProcessItemStreamAsync(
                           partitionKey,
                           itemId,
                           streamPayload,
                           operationType,
                           requestOptions,
                           cancellationToken : cancellationToken));
            }

            PartitionKeyMismatchRetryPolicy requestRetryPolicy = null;

            while (true)
            {
                partitionKey = await this.GetPartitionKeyValueFromStreamAsync(streamPayload, cancellationToken);

                ResponseMessage responseMessage = await this.ProcessItemStreamAsync(
                    partitionKey,
                    itemId,
                    streamPayload,
                    operationType,
                    requestOptions,
                    cancellationToken : cancellationToken);

                if (responseMessage.IsSuccessStatusCode)
                {
                    return(responseMessage);
                }

                if (requestRetryPolicy == null)
                {
                    requestRetryPolicy = new PartitionKeyMismatchRetryPolicy(await this.ClientContext.DocumentClient.GetCollectionCacheAsync(), null);
                }

                ShouldRetryResult retryResult = await requestRetryPolicy.ShouldRetryAsync(responseMessage, cancellationToken);

                if (!retryResult.ShouldRetry)
                {
                    return(responseMessage);
                }
            }
        }
        public async Task NotRetryOnSuccess()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                Mock.Of <ContainerInternal>(),
                new ResourceThrottleRetryPolicy(1));

            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(HttpStatusCode.OK);
            ShouldRetryResult shouldRetryResult      = await retryPolicy.ShouldRetryAsync(result.ToResponseMessage(), default);

            Assert.IsFalse(shouldRetryResult.ShouldRetry);
        }
        public async Task RetriesOn429()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                Mock.Of <ContainerInternal>(),
                new ResourceThrottleRetryPolicy(1));

            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult((HttpStatusCode)StatusCodes.TooManyRequests);
            ShouldRetryResult shouldRetryResult      = await retryPolicy.ShouldRetryAsync(result.ToResponseMessage(), default);

            Assert.IsTrue(shouldRetryResult.ShouldRetry);
        }
Exemple #27
0
        public async Task <ShouldRetryResult> ShouldRetryAsync(
            CosmosResponseMessage cosmosResponseMessage,
            CancellationToken cancellationToken)
        {
            ShouldRetryResult shouldRetryResult = await this.retryPolicy.ShouldRetryAsync(cosmosResponseMessage, cancellationToken);

            return(await this.ShouldRetryInternalAsync(
                       cosmosResponseMessage?.StatusCode,
                       cosmosResponseMessage?.Headers.SubStatusCode,
                       shouldRetryResult,
                       cancellationToken));
        }
Exemple #28
0
        public async Task <ShouldRetryResult> ShouldRetryAsync(Exception exception, CancellationToken cancellationToken)
        {
            ShouldRetryResult shouldRetry = await this.retryPolicy.ShouldRetryAsync(exception, cancellationToken);

            DocumentClientException clientException = exception as DocumentClientException;

            return(await this.ShouldRetryInternalAsync(
                       clientException?.StatusCode,
                       clientException?.GetSubStatus(),
                       shouldRetry,
                       cancellationToken));
        }
Exemple #29
0
        public async Task ShouldRetry_WithPolicy_On429()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                new ResourceThrottleRetryPolicy(1));
            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult((HttpStatusCode)StatusCodes.TooManyRequests);
            ItemBatchOperation operation             = new ItemBatchOperation(OperationType.Create, 0, Cosmos.PartitionKey.Null);

            operation.AttachContext(new ItemBatchOperationContext(string.Empty, retryPolicy));
            ShouldRetryResult shouldRetryResult = await operation.Context.ShouldRetryAsync(result, default(CancellationToken));

            Assert.IsTrue(shouldRetryResult.ShouldRetry);
        }
Exemple #30
0
        public async Task ShouldRetry_WithPolicy_OnSuccess()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkPartitionKeyRangeGoneRetryPolicy(
                new ResourceThrottleRetryPolicy(1));
            BatchOperationResult result    = new BatchOperationResult(HttpStatusCode.OK);
            ItemBatchOperation   operation = new ItemBatchOperation(OperationType.Create, 0);

            operation.AttachContext(new ItemBatchOperationContext(string.Empty, retryPolicy));
            ShouldRetryResult shouldRetryResult = await operation.Context.ShouldRetryAsync(result, default(CancellationToken));

            Assert.IsFalse(shouldRetryResult.ShouldRetry);
        }