public async Task <IReadOnlyList <FeedRange> > GetFeedRangesAsync( ITrace trace, CancellationToken cancellationToken = default) { PartitionKeyRangeCache partitionKeyRangeCache = await this.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(trace); string containerRId; containerRId = await this.GetCachedRIDAsync( forceRefresh : false, trace, cancellationToken); IReadOnlyList <PartitionKeyRange> partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, ContainerCore.allRanges, trace, forceRefresh : true); if (partitionKeyRanges == null) { string refreshedContainerRId; refreshedContainerRId = await this.GetCachedRIDAsync( forceRefresh : true, trace, cancellationToken); if (string.Equals(containerRId, refreshedContainerRId)) { throw CosmosExceptionFactory.CreateInternalServerErrorException( $"Container rid {containerRId} did not have a partition key range after refresh", headers: new Headers(), trace: trace); } partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, ContainerCore.allRanges, trace, forceRefresh : true); if (partitionKeyRanges == null) { throw CosmosExceptionFactory.CreateInternalServerErrorException( $"Container rid {containerRId} returned partitionKeyRanges null after Container RID refresh", headers: new Headers(), trace: trace); } } List <FeedRange> feedTokens = new List <FeedRange>(partitionKeyRanges.Count); foreach (PartitionKeyRange partitionKeyRange in partitionKeyRanges) { feedTokens.Add(new FeedRangeEpk(partitionKeyRange.ToRange())); } return(feedTokens); }
public async Task <IReadOnlyList <FeedRange> > GetFeedRangesAsync( CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken = default) { PartitionKeyRangeCache partitionKeyRangeCache = await this.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(); string containerRId = await this.GetRIDAsync(cancellationToken); IReadOnlyList <PartitionKeyRange> partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, new Range <string>( PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMinInclusive : true, isMaxInclusive : false), forceRefresh : true); List <FeedRange> feedTokens = new List <FeedRange>(partitionKeyRanges.Count); foreach (PartitionKeyRange partitionKeyRange in partitionKeyRanges) { feedTokens.Add(new FeedRangeEpk(partitionKeyRange.ToRange())); } return(feedTokens); }
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); }
public override async Task <IReadOnlyList <PartitionKeyRange> > TryGetOverlappingRangesAsync( string collectionResourceId, Range <string> range, bool forceRefresh = false) { PartitionKeyRangeCache partitionKeyRangeCache = await this.GetRoutingMapProviderAsync(); return(await partitionKeyRangeCache.TryGetOverlappingRangesAsync(collectionResourceId, range, forceRefresh)); }
private async Task <ShouldRetryResult> ShouldRetryInternalAsync( HttpStatusCode?statusCode, SubStatusCodes?subStatusCode, CancellationToken cancellationToken) { if (statusCode == HttpStatusCode.Gone) { this.retriesOn410++; if (this.retriesOn410 > MaxRetryOn410) { return(ShouldRetryResult.NoRetry()); } if (subStatusCode == SubStatusCodes.PartitionKeyRangeGone || subStatusCode == SubStatusCodes.CompletingSplit || subStatusCode == SubStatusCodes.CompletingPartitionMigration) { PartitionKeyRangeCache partitionKeyRangeCache = await this.container.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); string containerRid = await this.container.GetCachedRIDAsync( forceRefresh : false, NoOpTrace.Singleton, cancellationToken : cancellationToken); await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRid, FeedRangeEpk.FullRange.Range, NoOpTrace.Singleton, forceRefresh : true); return(ShouldRetryResult.RetryAfter(TimeSpan.Zero)); } if (subStatusCode == SubStatusCodes.NameCacheIsStale) { return(ShouldRetryResult.RetryAfter(TimeSpan.Zero)); } } // Batch API can return 413 which means the response is bigger than 4Mb. // Operations that exceed the 4Mb limit are returned as 413/3402, while the operations within the 4Mb limit will be 200 if (statusCode == HttpStatusCode.RequestEntityTooLarge && (int)subStatusCode == SubstatusCodeBatchResponseSizeExceeded) { return(ShouldRetryResult.RetryAfter(TimeSpan.Zero)); } return(null); }
public async Task GetChangeFeedTokensAsyncReturnsOnePerPartitionKeyRange() { // Setting mock to have 3 ranges, to generate 3 tokens MultiRangeMockDocumentClient documentClient = new MultiRangeMockDocumentClient(); using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); Mock <CosmosClientContext> mockContext = new Mock <CosmosClientContext>(); mockContext.Setup(x => x.ClientOptions).Returns(MockCosmosUtil.GetDefaultConfiguration()); mockContext.Setup(x => x.DocumentClient).Returns(documentClient); mockContext.Setup(x => x.SerializerCore).Returns(MockCosmosUtil.Serializer); mockContext.Setup(x => x.Client).Returns(client); mockContext.Setup(x => x.CreateLink(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())).Returns(UriFactory.CreateDocumentCollectionUri("test", "test").OriginalString); DatabaseInternal db = new DatabaseInlineCore(mockContext.Object, "test"); ContainerInternal container = new ContainerInlineCore(mockContext.Object, db, "test"); IEnumerable <string> tokens = await container.GetChangeFeedTokensAsync(); Assert.AreEqual(3, tokens.Count()); PartitionKeyRangeCache pkRangeCache = await documentClient.GetPartitionKeyRangeCacheAsync(); foreach (string token in tokens) { // Validate that each token represents a StandByFeedContinuationToken with a single Range List <CompositeContinuationToken> deserialized = JsonConvert.DeserializeObject <List <CompositeContinuationToken> >(token); Assert.AreEqual(1, deserialized.Count); CompositeContinuationToken compositeToken = deserialized[0]; IReadOnlyList <Documents.PartitionKeyRange> rangesForTheToken = await pkRangeCache.TryGetOverlappingRangesAsync("", compositeToken.Range); // Token represents one range Assert.AreEqual(1, rangesForTheToken.Count); Assert.AreEqual(rangesForTheToken[0].MinInclusive, compositeToken.Range.Min); Assert.AreEqual(rangesForTheToken[0].MaxExclusive, compositeToken.Range.Max); } }
public async Task <IReadOnlyList <FeedRange> > GetFeedRangesAsync( CosmosDiagnosticsContext diagnosticsContext, ITrace trace, CancellationToken cancellationToken = default) { PartitionKeyRangeCache partitionKeyRangeCache = await this.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(); string containerRId; using (diagnosticsContext.CreateScope(nameof(GetCachedRIDAsync))) { containerRId = await this.GetCachedRIDAsync( forceRefresh : false, cancellationToken); } IReadOnlyList <PartitionKeyRange> partitionKeyRanges; using (diagnosticsContext.CreateScope(nameof(partitionKeyRangeCache.TryGetOverlappingRangesAsync))) { partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, ContainerCore.allRanges, forceRefresh : true); } if (partitionKeyRanges == null) { string refreshedContainerRId; using (diagnosticsContext.CreateScope("GetRIDAsyncForceRefresh")) { refreshedContainerRId = await this.GetCachedRIDAsync( forceRefresh : true, cancellationToken); } if (string.Equals(containerRId, refreshedContainerRId)) { throw CosmosExceptionFactory.CreateInternalServerErrorException( $"Container rid {containerRId} did not have a partition key range after refresh", diagnosticsContext: diagnosticsContext); } using (diagnosticsContext.CreateScope(nameof(partitionKeyRangeCache.TryGetOverlappingRangesAsync))) { partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, ContainerCore.allRanges, forceRefresh : true); } if (partitionKeyRanges == null) { throw CosmosExceptionFactory.CreateInternalServerErrorException( $"Container rid {containerRId} returned partitionKeyRanges null after Container RID refresh", diagnosticsContext: diagnosticsContext); } } List <FeedRange> feedTokens = new List <FeedRange>(partitionKeyRanges.Count); foreach (PartitionKeyRange partitionKeyRange in partitionKeyRanges) { feedTokens.Add(new FeedRangeEpk(partitionKeyRange.ToRange())); } return(feedTokens); }
async Task <IEnumerable <string> > GetPartitionKeyRangesAsync( FeedToken feedToken, CancellationToken cancellationToken = default(CancellationToken)) { if (feedToken is FeedTokenEPKRange feedTokenEPKRange) { PartitionKeyRangeCache partitionKeyRangeCache = await this.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(); string containerRId = await this.GetRIDAsync(cancellationToken); IReadOnlyList <Documents.PartitionKeyRange> partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync(containerRId, feedTokenEPKRange.CompleteRange, forceRefresh : false); return(partitionKeyRanges.Select(partitionKeyRange => partitionKeyRange.Id)); } if (feedToken is FeedTokenPartitionKeyRange feedTokenPartitionKeyRange) { if (feedTokenPartitionKeyRange.FeedTokenEPKRange != null) { return(await this.GetPartitionKeyRangesAsync(feedTokenPartitionKeyRange.FeedTokenEPKRange, cancellationToken)); } return(new List <string>() { feedTokenPartitionKeyRange.PartitionKeyRangeId }); } if (feedToken is FeedTokenPartitionKey feedTokenPartitionKey) { CollectionRoutingMap collectionRoutingMap = await this.GetRoutingMapAsync(cancellationToken); PartitionKeyDefinition partitionKeyDefinition = await this.GetPartitionKeyDefinitionAsync(cancellationToken); PartitionKeyInternal partitionKeyInternal = feedTokenPartitionKey.PartitionKey.InternalKey; string effectivePartitionKeyString = partitionKeyInternal.GetEffectivePartitionKeyString(partitionKeyDefinition); string partitionKeyRangeId = collectionRoutingMap.GetRangeByEffectivePartitionKey(effectivePartitionKeyString).Id; return(new List <string>() { partitionKeyRangeId }); } throw new ArgumentException(nameof(feedToken), ClientResources.FeedToken_UnrecognizedFeedToken); }