public async Task InexistentPKRangeId() { ContainerInternal container = null; try { // Create a container large enough to have at least 2 partitions ContainerResponse containerResponse = await this.database.CreateContainerAsync( id : Guid.NewGuid().ToString(), partitionKeyPath : "/pk"); container = (ContainerInlineCore)containerResponse; string feedRangeSerialization = JsonConvert.SerializeObject(new { PKRangeId = "10" }); FeedRange feedRange = FeedRange.FromJsonString(feedRangeSerialization); FeedIterator <ToDoActivity> feedIterator = container.GetItemQueryIterator <ToDoActivity>( queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedRange, continuationToken: null); CosmosException exception = await Assert.ThrowsExceptionAsync <CosmosException>(() => feedIterator.ReadNextAsync()); Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); Assert.AreEqual((int)Documents.SubStatusCodes.PartitionKeyRangeGone, exception.SubStatusCode); } finally { await container?.DeleteContainerAsync(); } }
public async Task GetTargetPartitionKeyRangesAsyncWithFeedRange() { ContainerInternal container = null; try { // Create a container large enough to have at least 2 partitions ContainerResponse containerResponse = await this.database.CreateContainerAsync( id : Guid.NewGuid().ToString(), partitionKeyPath : "/pk", throughput : 15000); container = (ContainerInlineCore)containerResponse; // Get all the partition key ranges to verify there is more than one partition IRoutingMapProvider routingMapProvider = await this.cosmosClient.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties( containerResponse.Resource.ResourceId, null, containerResponse.Resource.PartitionKey); IReadOnlyList <FeedRange> feedTokens = await container.GetFeedRangesAsync(); Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); // There should only be one range since we get 1 FeedRange per range foreach (FeedRange feedToken in feedTokens) { List <PartitionKeyRange> partitionKeyRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( queryClient : new CosmosQueryClientCore(container.ClientContext, container), resourceLink : container.LinkUri, partitionedQueryExecutionInfo : null, containerQueryProperties : containerQueryProperties, properties : null, feedRangeInternal : feedToken as FeedRangeInternal, NoOpTrace.Singleton); Assert.IsTrue(partitionKeyRanges.Count == 1, "Only 1 partition key range should be selected since the FeedRange represents a single range."); } } finally { await container?.DeleteContainerAsync(); } }
public async Task ParallelizeQueryThroughTokens_OfT() { ContainerInternal container = null; try { // Create a container large enough to have at least 2 partitions ContainerResponse containerResponse = await this.database.CreateContainerAsync( id : Guid.NewGuid().ToString(), partitionKeyPath : "/id", throughput : 15000); container = (ContainerInlineCore)containerResponse; List <string> generatedIds = Enumerable.Range(0, 1000).Select(n => $"BasicItem{n}").ToList(); foreach (string id in generatedIds) { string item = $@" {{ ""id"": ""{id}"" }}"; using (ResponseMessage createResponse = await container.CreateItemStreamAsync( QueryFeedRangeTests.GenerateStreamFromString(item), new Cosmos.PartitionKey(id))) { Assert.IsTrue(createResponse.IsSuccessStatusCode); } } IReadOnlyList <FeedRange> feedTokens = await container.GetFeedRangesAsync(); Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); List <Task <List <string> > > tasks = feedTokens.Select(async feedToken => { List <string> results = new List <string>(); FeedIterator <ToDoActivity> feedIterator = container.GetItemQueryIterator <ToDoActivity>(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); string continuation = null; while (feedIterator.HasMoreResults) { FeedResponse <ToDoActivity> response = await feedIterator.ReadNextAsync(); foreach (ToDoActivity toDoActivity in response) { results.Add(toDoActivity.id); } continuation = response.ContinuationToken; break; } feedIterator = container.GetItemQueryIterator <ToDoActivity>(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); while (feedIterator.HasMoreResults) { FeedResponse <ToDoActivity> response = await feedIterator.ReadNextAsync(); foreach (ToDoActivity toDoActivity in response) { results.Add(toDoActivity.id); } } return(results); }).ToList(); await Task.WhenAll(tasks); CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); } finally { await container?.DeleteContainerAsync(); } }
public async Task ReadFeedIteratorCore_CrossPartitionBiDirectional(bool useStatelessIteration) { ContainerInternal container = null; try { ContainerResponse containerResponse = await this.database.CreateContainerAsync( new ContainerProperties(id : Guid.NewGuid().ToString(), partitionKeyPath : "/id"), throughput : 50000, cancellationToken : this.cancellationToken); container = (ContainerInlineCore)containerResponse; // Create Items const int total = 30; QueryRequestOptions requestOptions = new QueryRequestOptions() { MaxItemCount = 10 }; List <string> items = new List <string>(); for (int i = 0; i < total; i++) { string item = $@" {{ ""id"": ""{i}"" }}"; using (ResponseMessage createResponse = await container.CreateItemStreamAsync( ReadFeedRangeTests.GenerateStreamFromString(item), new Cosmos.PartitionKey(i.ToString()))) { Assert.IsTrue(createResponse.IsSuccessStatusCode); } } string continuation = null; FeedIterator iter = container.GetItemQueryStreamIterator( continuationToken: continuation, requestOptions: requestOptions); int count = 0; List <string> forwardOrder = new List <string>(); while (iter.HasMoreResults) { if (useStatelessIteration) { iter = container.GetItemQueryStreamIterator( continuationToken: continuation, requestOptions: requestOptions); } using (ResponseMessage response = await iter.ReadNextAsync()) { Assert.IsNotNull(response); continuation = response.ContinuationToken; using (StreamReader reader = new StreamReader(response.Content)) { string json = await reader.ReadToEndAsync(); JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); count += documents.Count; if (documents.Any()) { forwardOrder.Add(documents.First().SelectToken("id").ToString()); } } } } Assert.IsNotNull(forwardOrder); Assert.AreEqual(total, count); Assert.IsFalse(forwardOrder.Where(x => string.IsNullOrEmpty(x)).Any()); requestOptions.Properties = requestOptions.Properties = new Dictionary <string, object>() { { Documents.HttpConstants.HttpHeaders.EnumerationDirection, (byte)BinaryScanDirection.Reverse }, }; count = 0; List <string> reverseOrder = new List <string>(); continuation = null; iter = container .GetItemQueryStreamIterator(queryDefinition: null, continuationToken: continuation, requestOptions: requestOptions); while (iter.HasMoreResults) { if (useStatelessIteration) { iter = container .GetItemQueryStreamIterator(queryDefinition: null, continuationToken: continuation, requestOptions: requestOptions); } using (ResponseMessage response = await iter.ReadNextAsync()) { continuation = response.ContinuationToken; Assert.IsNotNull(response); using (StreamReader reader = new StreamReader(response.Content)) { string json = await reader.ReadToEndAsync(); JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); count += documents.Count; if (documents.Any()) { reverseOrder.Add(documents.First().SelectToken("id").ToString()); } } } } Assert.IsNotNull(reverseOrder); Assert.AreEqual(total, count); forwardOrder.Reverse(); CollectionAssert.AreEqual(forwardOrder, reverseOrder); Assert.IsFalse(reverseOrder.Where(x => string.IsNullOrEmpty(x)).Any()); } finally { await container?.DeleteContainerAsync(); } }