public async Task ReadFeedAsync() { int numItems = 100; IDocumentContainer documentContainer = await this.CreateDocumentContainerAsync(numItems); CrossPartitionReadFeedAsyncEnumerator enumerator = CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, new QueryRequestOptions(), new CrossFeedRangeState <ReadFeedState>(ReadFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), pageSize: 10, cancellationToken: default); int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. Trace rootTrace; using (rootTrace = Trace.GetRootTrace("Cross Partition Read Feed")) { while (await enumerator.MoveNextAsync(rootTrace)) { numChildren++; } } string traceString = TraceWriter.TraceToText(rootTrace); Console.WriteLine(traceString); Assert.AreEqual(numChildren, rootTrace.Children.Count); }
public override async Task <ResponseMessage> ReadNextAsync( ITrace trace, CancellationToken cancellationToken = default) { if (trace == null) { throw new ArgumentNullException(nameof(trace)); } cancellationToken.ThrowIfCancellationRequested(); if (!this.hasMoreResults) { throw new InvalidOperationException("Should not be calling FeedIterator that does not have any more results"); } if (this.monadicEnumerator.Failed) { this.hasMoreResults = false; CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(this.monadicEnumerator.Exception); return(new ResponseMessage( statusCode: System.Net.HttpStatusCode.BadRequest, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, trace: trace)); } CrossPartitionReadFeedAsyncEnumerator enumerator = this.monadicEnumerator.Result; TryCatch <CrossFeedRangePage <Pagination.ReadFeedPage, ReadFeedState> > monadicPage; try { if (!await enumerator.MoveNextAsync(trace)) { throw new InvalidOperationException("Should not be calling enumerator that does not have any more results"); } monadicPage = enumerator.Current; } catch (Exception ex) { monadicPage = TryCatch <CrossFeedRangePage <Pagination.ReadFeedPage, ReadFeedState> > .FromException(ex); } if (monadicPage.Failed) { CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(monadicPage.Exception); if (!IsRetriableException(cosmosException)) { this.hasMoreResults = false; } return(new ResponseMessage( statusCode: cosmosException.StatusCode, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, trace: trace)); } CrossFeedRangePage <Pagination.ReadFeedPage, ReadFeedState> crossFeedRangePage = monadicPage.Result; if (crossFeedRangePage.State == default) { this.hasMoreResults = false; } // Make the continuation token match the older format: string continuationToken; if (crossFeedRangePage.State != null) { List <CompositeContinuationToken> compositeContinuationTokens = new List <CompositeContinuationToken>(); CrossFeedRangeState <ReadFeedState> crossFeedRangeState = crossFeedRangePage.State; for (int i = 0; i < crossFeedRangeState.Value.Length; i++) { FeedRangeState <ReadFeedState> feedRangeState = crossFeedRangeState.Value.Span[i]; FeedRangeEpk feedRange; if (feedRangeState.FeedRange is FeedRangeEpk feedRangeEpk) { feedRange = feedRangeEpk; } else { feedRange = FeedRangeEpk.FullRange; } ReadFeedState readFeedState = feedRangeState.State; CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken() { Range = feedRange.Range, Token = readFeedState is ReadFeedBeginningState ? null : ((ReadFeedContinuationState)readFeedState).ContinuationToken.ToString(), }; compositeContinuationTokens.Add(compositeContinuationToken); } FeedRangeInternal outerFeedRange; if ((this.queryRequestOptions != null) && this.queryRequestOptions.PartitionKey.HasValue) { outerFeedRange = new FeedRangePartitionKey(this.queryRequestOptions.PartitionKey.Value); } else if ((this.queryRequestOptions != null) && (this.queryRequestOptions.FeedRange != null)) { outerFeedRange = (FeedRangeInternal)this.queryRequestOptions.FeedRange; } else { outerFeedRange = FeedRangeEpk.FullRange; } FeedRangeCompositeContinuation feedRangeCompositeContinuation = new FeedRangeCompositeContinuation( containerRid: string.Empty, feedRange: outerFeedRange, compositeContinuationTokens); continuationToken = feedRangeCompositeContinuation.ToString(); } else { continuationToken = null; } Pagination.ReadFeedPage page = crossFeedRangePage.Page; Headers headers = new Headers() { RequestCharge = page.RequestCharge, ActivityId = page.ActivityId, ContinuationToken = continuationToken, }; foreach (KeyValuePair <string, string> kvp in page.AdditionalHeaders) { headers[kvp.Key] = kvp.Value; } return(new ResponseMessage( statusCode: System.Net.HttpStatusCode.OK, requestMessage: default,
public async Task ScenariosAsync() { List <Input> inputs = new List <Input>(); int startLineNumber; int endLineNumber; //---------------------------------------------------------------- // ReadFeed //---------------------------------------------------------------- { startLineNumber = GetLineNumber(); int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems); CrossPartitionReadFeedAsyncEnumerator enumerator = CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, new CrossFeedRangeState <ReadFeedState>(ReadFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), new ReadFeedPaginationOptions(pageSizeHint: 10), cancellationToken: default); int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { while (await enumerator.MoveNextAsync(rootTrace)) { numChildren++; } } Assert.AreEqual(numChildren, rootTrace.Children.Count); endLineNumber = GetLineNumber(); inputs.Add(new Input("ReadFeed", rootTrace, startLineNumber, endLineNumber)); } //---------------------------------------------------------------- //---------------------------------------------------------------- // ChangeFeed //---------------------------------------------------------------- { startLineNumber = GetLineNumber(); int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems); CrossPartitionChangeFeedAsyncEnumerator enumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( documentContainer, new CrossFeedRangeState <ChangeFeedState>( ChangeFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), new ChangeFeedPaginationOptions( ChangeFeedMode.Incremental, pageSizeHint: int.MaxValue), cancellationToken: default); int numChildren = 0; TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { while (await enumerator.MoveNextAsync(rootTrace)) { numChildren++; if (enumerator.Current.Result.Page is ChangeFeedNotModifiedPage) { break; } } } Assert.AreEqual(numChildren, rootTrace.Children.Count); endLineNumber = GetLineNumber(); inputs.Add(new Input("ChangeFeed", rootTrace, startLineNumber, endLineNumber)); } //---------------------------------------------------------------- //---------------------------------------------------------------- // Query //---------------------------------------------------------------- { startLineNumber = GetLineNumber(); int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems); IQueryPipelineStage pipelineStage = CreatePipeline(documentContainer, "SELECT * FROM c", pageSize: 10); TraceForBaselineTesting rootTrace; int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { while (await pipelineStage.MoveNextAsync(rootTrace)) { numChildren++; } } Assert.AreEqual(numChildren, rootTrace.Children.Count); endLineNumber = GetLineNumber(); inputs.Add(new Input("Query", rootTrace, startLineNumber, endLineNumber)); } //---------------------------------------------------------------- this.ExecuteTestSuite(inputs); }
/// <summary> /// Get the next set of results from the cosmos service /// </summary> /// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param> /// <returns>A query response from cosmos service</returns> public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); if (!this.hasMoreResults) { throw new InvalidOperationException("Should not be calling FeedIterator that does not have any more results"); } if (this.monadicEnumerator.Failed) { this.hasMoreResults = false; CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(this.monadicEnumerator.Exception); return(new ResponseMessage( statusCode: System.Net.HttpStatusCode.BadRequest, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, diagnostics: cosmosException.DiagnosticsContext)); } CrossPartitionReadFeedAsyncEnumerator enumerator = this.monadicEnumerator.Result; TryCatch <ReadFeedPage> monadicPage; try { if (!await enumerator.MoveNextAsync()) { throw new InvalidOperationException("Should not be calling enumerator that does not have any more results"); } monadicPage = enumerator.Current; } catch (Exception ex) { monadicPage = TryCatch <ReadFeedPage> .FromException(ex); } if (monadicPage.Failed) { CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(monadicPage.Exception); if (!IsRetriableException(cosmosException)) { this.hasMoreResults = false; } return(new ResponseMessage( statusCode: cosmosException.StatusCode, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, diagnostics: cosmosException.DiagnosticsContext)); } ReadFeedPage readFeedPage = monadicPage.Result; if (readFeedPage.State == default) { this.hasMoreResults = false; } // Make the continuation token match the older format: string continuationToken; if (readFeedPage.State != null) { List <CompositeContinuationToken> compositeContinuationTokens = new List <CompositeContinuationToken>(); CosmosArray compositeContinuationTokensCosmosArray = (CosmosArray)readFeedPage.State.ContinuationToken; foreach (CosmosElement arrayItem in compositeContinuationTokensCosmosArray) { ReadFeedContinuationToken readFeedContinuationToken = ReadFeedContinuationToken.MonadicConvertFromCosmosElement(arrayItem).Result; FeedRangeEpk feedRangeEpk = (FeedRangeEpk)readFeedContinuationToken.Range; ReadFeedState readFeedState = readFeedContinuationToken.State; CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken() { Range = feedRangeEpk.Range, Token = readFeedState.ContinuationToken.ToString(), }; compositeContinuationTokens.Add(compositeContinuationToken); } FeedRangeCompositeContinuation feedRangeCompositeContinuation = new FeedRangeCompositeContinuation( containerRid: string.Empty, feedRange: FeedRangeEpk.FullRange, compositeContinuationTokens); continuationToken = feedRangeCompositeContinuation.ToString(); } else { continuationToken = null; } return(new ResponseMessage( statusCode: System.Net.HttpStatusCode.OK, requestMessage: default,