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(); } }