public async Task TestCosmosOrderByQueryExecutionContextWithEmptyPagesAndSplitAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetSplitScenarios(); Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullConitnuationToken = null; if (createInitialContinuationToken) { ToDoItem itemToRepresentPreviousQuery = ToDoItem.CreateItems( 1, "itemToRepresentPreviousQuery", MockQueryFactory.DefaultCollectionRid).First(); initialContinuationToken = $" - RID:{itemToRepresentPreviousQuery._rid} ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; List <OrderByItem> orderByItems = new List <OrderByItem>() { new OrderByItem(CosmosObject.CreateFromBuffer(Encoding.UTF8.GetBytes("{\"item\":\"2c4ce711-13c3-4c93-817c-49287b71b6c3\"}"))) }; OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( compositeContinuationToken: compositeContinuation, orderByItems: orderByItems, rid: itemToRepresentPreviousQuery._rid, skipCount: 0, filter: null); fullConitnuationToken = CosmosArray.Create( new List <CosmosElement>() { OrderByContinuationToken.ToCosmosElement(orderByContinuationToken) }).ToString(); } IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: true, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); // Order by drains the partitions until it finds an item // If there are no items then it's not possible to have a continuation token if (allItems.Count == 0 && createInitialContinuationToken) { continue; } CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); QueryInfo queryInfo = new QueryInfo() { OrderBy = new SortOrder[] { SortOrder.Ascending }, OrderByExpressions = new string[] { "id" } }; CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = queryInfo }, partitionKeyRanges: new List <PartitionKeyRange>() { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null, returnResultsInDeterministicOrder: true, testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false)); IDocumentQueryExecutionComponent executionContext = (await CosmosOrderByItemQueryExecutionContext.TryCreateAsync( context, initParams, fullConitnuationToken, this.cancellationToken)).Result; // For order by it will drain all the pages till it gets a value. if (allItems.Count == 0) { Assert.IsTrue(executionContext.IsDone); continue; } Assert.IsTrue(!executionContext.IsDone); // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync( maxPageSize, this.cancellationToken); string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } Assert.AreEqual(allItems.Count, itemsRead.Count); CollectionAssert.AreEqual(allItems.ToList(), itemsRead, new ToDoItemComparer()); } }
public async Task TestCosmosCrossPartitionQueryExecutionContextWithFailuresAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetFailureScenarios(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullConitnuationToken = null; if (createInitialContinuationToken) { initialContinuationToken = " - RID:02FYAIvUH1kCAAAAAAAAAA ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; fullConitnuationToken = CosmosArray.Create( new List <CosmosElement>() { CompositeContinuationToken.ToCosmosElement(compositeContinuation) }).ToString(); } Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: false, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = new QueryInfo() }, partitionKeyRanges: new List <PartitionKeyRange>() { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null, returnResultsInDeterministicOrder: true, testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false)); IDocumentQueryExecutionComponent executionContext = (await CosmosParallelItemQueryExecutionContext.TryCreateAsync( context, initParams, fullConitnuationToken, this.cancellationToken)).Result; // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); Assert.IsTrue(!executionContext.IsDone); QueryResponseCore?failure = null; while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync(maxPageSize, this.cancellationToken); if (queryResponse.IsSuccess) { string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } else { Assert.IsNull(failure, "There should only be one error"); failure = queryResponse; } } Assert.IsNotNull(failure); Assert.AreEqual((HttpStatusCode)429, failure.Value.StatusCode); Assert.IsNull(failure.Value.ErrorMessage); Assert.AreEqual(allItems.Count, itemsRead.Count); List <ToDoItem> exepected = allItems.OrderBy(x => x.id).ToList(); List <ToDoItem> actual = itemsRead.OrderBy(x => x.id).ToList(); CollectionAssert.AreEqual(exepected, actual, new ToDoItemComparer()); } }
public async Task TestCosmosCrossPartitionQueryExecutionContextWithEmptyPagesAndSplitAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetSplitScenarios(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullConitnuationToken = null; if (createInitialContinuationToken) { initialContinuationToken = " - RID:02FYAIvUH1kCAAAAAAAAAA ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; fullConitnuationToken = JsonConvert.SerializeObject(new CompositeContinuationToken[] { compositeContinuation }); } Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: false, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = new QueryInfo() }, partitionKeyRanges: new List <PartitionKeyRange>() { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null); CosmosParallelItemQueryExecutionContext executionContext = (await CosmosParallelItemQueryExecutionContext.TryCreateAsync( context, initParams, fullConitnuationToken, this.cancellationToken)).Result; // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); Assert.IsTrue(!executionContext.IsDone); while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync(maxPageSize, this.cancellationToken); string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } Assert.AreEqual(allItems.Count, itemsRead.Count); List <ToDoItem> exepected = allItems.OrderBy(x => x.id).ToList(); List <ToDoItem> actual = itemsRead.OrderBy(x => x.id).ToList(); CollectionAssert.AreEqual(exepected, actual, new ToDoItemComparer()); } }
public static async Task <TryCatch <CosmosQueryExecutionContext> > TryCreateAsync( ExecutionEnvironment executionEnvironment, CosmosQueryContext queryContext, CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams, CosmosElement requestContinuationToken, CancellationToken cancellationToken) { if (queryContext == null) { throw new ArgumentNullException(nameof(initParams)); } cancellationToken.ThrowIfCancellationRequested(); QueryInfo queryInfo = initParams.PartitionedQueryExecutionInfo.QueryInfo; int initialPageSize = initParams.InitialPageSize; if (queryInfo.HasGroupBy) { // The query will block until all groupings are gathered so we might as well speed up the process. initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: initParams.SqlQuerySpec, collectionRid: initParams.CollectionRid, partitionedQueryExecutionInfo: initParams.PartitionedQueryExecutionInfo, partitionKeyRanges: initParams.PartitionKeyRanges, initialPageSize: int.MaxValue, maxConcurrency: initParams.MaxConcurrency, maxItemCount: int.MaxValue, maxBufferedItemCount: initParams.MaxBufferedItemCount, returnResultsInDeterministicOrder: true, testSettings: initParams.TestSettings); } Task <TryCatch <IDocumentQueryExecutionComponent> > tryCreateOrderByComponentAsync(CosmosElement continuationToken) { return(CosmosOrderByItemQueryExecutionContext.TryCreateAsync( queryContext, initParams, continuationToken, cancellationToken)); } Task <TryCatch <IDocumentQueryExecutionComponent> > tryCreateParallelComponentAsync(CosmosElement continuationToken) { return(CosmosParallelItemQueryExecutionContext.TryCreateAsync( queryContext, initParams, continuationToken, cancellationToken)); } Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreatePipelineAsync; if (queryInfo.HasOrderBy) { tryCreatePipelineAsync = tryCreateOrderByComponentAsync; } else { tryCreatePipelineAsync = tryCreateParallelComponentAsync; } if (queryInfo.HasAggregates && !queryInfo.HasGroupBy) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await AggregateDocumentQueryExecutionComponent.TryCreateAsync( executionEnvironment, queryInfo.Aggregates, queryInfo.GroupByAliasToAggregateType, queryInfo.GroupByAliases, queryInfo.HasSelectValue, continuationToken, tryCreateSourceAsync)); }; } if (queryInfo.HasDistinct) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await DistinctDocumentQueryExecutionComponent.TryCreateAsync( executionEnvironment, continuationToken, tryCreateSourceAsync, queryInfo.DistinctType)); }; } if (queryInfo.HasGroupBy) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await GroupByDocumentQueryExecutionComponent.TryCreateAsync( executionEnvironment, continuationToken, tryCreateSourceAsync, queryInfo.GroupByAliasToAggregateType, queryInfo.GroupByAliases, queryInfo.HasSelectValue)); }; } if (queryInfo.Offset.HasValue) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await SkipDocumentQueryExecutionComponent.TryCreateAsync( executionEnvironment, queryInfo.Offset.Value, continuationToken, tryCreateSourceAsync)); }; } if (queryInfo.Limit.HasValue) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.TryCreateLimitDocumentQueryExecutionComponentAsync( executionEnvironment, queryInfo.Limit.Value, continuationToken, tryCreateSourceAsync)); }; } if (queryInfo.Top.HasValue) { Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync = tryCreatePipelineAsync; tryCreatePipelineAsync = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.TryCreateTopDocumentQueryExecutionComponentAsync( executionEnvironment, queryInfo.Top.Value, continuationToken, tryCreateSourceAsync)); }; } return((await tryCreatePipelineAsync(requestContinuationToken)) .Try <CosmosQueryExecutionContext>((source) => new PipelinedDocumentQueryExecutionContext(source, initialPageSize))); }
public async Task TestCosmosOrderByQueryExecutionContextWithFailurePageAsync(bool createInitialContinuationToken) { int maxPageSize = 5; List <MockPartitionResponse[]> mockResponsesScenario = MockQueryFactory.GetFailureScenarios(); Mock <CosmosQueryClient> mockQueryClient = new Mock <CosmosQueryClient>(); foreach (MockPartitionResponse[] mockResponse in mockResponsesScenario) { string initialContinuationToken = null; string fullConitnuationToken = null; if (createInitialContinuationToken) { ToDoItem itemToRepresentPreviousQuery = ToDoItem.CreateItems( 1, "itemToRepresentPreviousQuery", MockQueryFactory.DefaultCollectionRid).First(); initialContinuationToken = $" - RID:{itemToRepresentPreviousQuery._rid} ==#RT:1#TRC:1"; CompositeContinuationToken compositeContinuation = new CompositeContinuationToken() { Range = new Documents.Routing.Range <string>( min: MockQueryFactory.DefaultPartitionKeyRange.MinInclusive, max: MockQueryFactory.DefaultPartitionKeyRange.MaxExclusive, isMaxInclusive: false, isMinInclusive: true), Token = initialContinuationToken }; List <OrderByItem> orderByItems = new List <OrderByItem>() { new OrderByItem(CosmosObject.CreateFromBuffer(Encoding.UTF8.GetBytes("{\"item\":\"2c4ce711-13c3-4c93-817c-49287b71b6c3\"}"))) }; OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( compositeContinuationToken: compositeContinuation, orderByItems: orderByItems, rid: itemToRepresentPreviousQuery._rid, skipCount: 0, filter: null); fullConitnuationToken = JsonConvert.SerializeObject(new OrderByContinuationToken[] { orderByContinuationToken }); } IList <ToDoItem> allItems = MockQueryFactory.GenerateAndMockResponse( mockQueryClient, isOrderByQuery: true, sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, containerRid: MockQueryFactory.DefaultCollectionRid, initContinuationToken: initialContinuationToken, maxPageSize: maxPageSize, mockResponseForSinglePartition: mockResponse, cancellationTokenForMocks: this.cancellationToken); // Order by drains the partitions until it finds an item // If there are no items then it's not possible to have a continuation token if (allItems.Count == 0 && createInitialContinuationToken) { continue; } CosmosQueryContext context = MockQueryFactory.CreateContext( mockQueryClient.Object); QueryInfo queryInfo = new QueryInfo() { OrderBy = new SortOrder[] { SortOrder.Ascending }, OrderByExpressions = new string[] { "id" } }; CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( sqlQuerySpec: MockQueryFactory.DefaultQuerySpec, collectionRid: MockQueryFactory.DefaultCollectionRid, partitionedQueryExecutionInfo: new PartitionedQueryExecutionInfo() { QueryInfo = queryInfo }, partitionKeyRanges: new List <PartitionKeyRange>() { MockQueryFactory.DefaultPartitionKeyRange }, initialPageSize: maxPageSize, maxConcurrency: null, maxItemCount: maxPageSize, maxBufferedItemCount: null, testSettings: new Query.Core.TestInjections(simulate429s: false, simulateEmptyPages: false)); TryCatch <CosmosOrderByItemQueryExecutionContext> tryCreate = await CosmosOrderByItemQueryExecutionContext.TryCreateAsync( context, initParams, fullConitnuationToken, this.cancellationToken); if (tryCreate.Succeeded) { CosmosOrderByItemQueryExecutionContext executionContext = tryCreate.Result; Assert.IsTrue(!executionContext.IsDone); // Read all the pages from both splits List <ToDoItem> itemsRead = new List <ToDoItem>(); QueryResponseCore?failure = null; while (!executionContext.IsDone) { QueryResponseCore queryResponse = await executionContext.DrainAsync( maxPageSize, this.cancellationToken); if (queryResponse.IsSuccess) { string responseContinuationToken = queryResponse.ContinuationToken; foreach (CosmosElement element in queryResponse.CosmosElements) { string jsonValue = element.ToString(); ToDoItem item = JsonConvert.DeserializeObject <ToDoItem>(jsonValue); itemsRead.Add(item); } } else { Assert.IsNull(failure, "There should only be one error"); failure = queryResponse; } } Assert.IsNotNull(failure); Assert.AreEqual((HttpStatusCode)429, failure.Value.StatusCode); Assert.IsNull(failure.Value.ErrorMessage); Assert.AreEqual(0 /*We don't get any items, since we don't buffer the failure anymore*/, itemsRead.Count); //CollectionAssert.AreEqual(allItems.ToList(), itemsRead, new ToDoItemComparer()); } else { CosmosException cosmosException = tryCreate.Exception as CosmosException; Assert.IsNotNull(cosmosException); Assert.AreEqual((HttpStatusCode)429, cosmosException.StatusCode); } } }