private static async Task <(int, ChangeFeedCrossFeedRangeState)> PartialDrainAsync(IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable) { ChangeFeedCrossFeedRangeState state = default; int totalCount = 0; await foreach (TryCatch <ChangeFeedPage> monadicPage in asyncEnumerable) { monadicPage.ThrowIfFailed(); ChangeFeedPage page = monadicPage.Result; state = page.State; if (page.NotModified) { break; } totalCount += page.Documents.Count; } return(totalCount, state); }
public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); TryCatch <CrossPartitionChangeFeedAsyncEnumerator> monadicEnumerator = await this.lazyMonadicEnumerator.GetValueAsync(cancellationToken); if (monadicEnumerator.Failed) { Exception createException = monadicEnumerator.Exception; CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(createException); return(new ResponseMessage( cosmosException.StatusCode, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, diagnostics: new CosmosDiagnosticsContextCore())); } CrossPartitionChangeFeedAsyncEnumerator enumerator = monadicEnumerator.Result; if (!await enumerator.MoveNextAsync()) { throw new InvalidOperationException("ChangeFeed enumerator should always have a next continuation"); } if (enumerator.Current.Failed) { CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(enumerator.Current.Exception); if (!IsRetriableException(cosmosException)) { this.hasMoreResults = false; } return(new ResponseMessage( cosmosException.StatusCode, requestMessage: null, headers: cosmosException.Headers, cosmosException: cosmosException, diagnostics: new CosmosDiagnosticsContextCore())); } ChangeFeedPage changeFeedPage = enumerator.Current.Result; ResponseMessage responseMessage; if (changeFeedPage is ChangeFeedSuccessPage changeFeedSuccessPage) { responseMessage = new ResponseMessage(statusCode: System.Net.HttpStatusCode.OK) { Content = changeFeedSuccessPage.Content }; } else { responseMessage = new ResponseMessage(statusCode: System.Net.HttpStatusCode.NotModified); } CosmosElement innerContinuationToken = ((ChangeFeedStateContinuation)changeFeedPage.State).ContinuationToken; string continuationToken; if (this.changeFeedRequestOptions.EmitOldContinuationToken) { List <ChangeFeedContinuationToken> parsedChangeFeedTokens = new List <ChangeFeedContinuationToken>(); CosmosArray changeFeedTokens = (CosmosArray)innerContinuationToken; foreach (CosmosElement changeFeedToken in changeFeedTokens) { parsedChangeFeedTokens.Add(ChangeFeedContinuationToken.MonadicConvertFromCosmosElement(changeFeedToken).Result); } List <CompositeContinuationToken> compositeContinuationTokens = new List <CompositeContinuationToken>(); foreach (ChangeFeedContinuationToken changeFeedContinuationToken in parsedChangeFeedTokens) { string token = changeFeedContinuationToken.State is ChangeFeedStateContinuation changeFeedStateContinuation ? ((CosmosString)changeFeedStateContinuation.ContinuationToken).Value : null; Documents.Routing.Range <string> range = ((FeedRangeEpk)changeFeedContinuationToken.Range).Range; CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken() { Range = range, Token = token, }; compositeContinuationTokens.Add(compositeContinuationToken); } FeedRangeCompositeContinuation feedRangeCompositeContinuationToken = new FeedRangeCompositeContinuation( await this.documentContainer.GetResourceIdentifierAsync(cancellationToken), FeedRangeEpk.FullRange, compositeContinuationTokens); continuationToken = feedRangeCompositeContinuationToken.ToString(); } else { continuationToken = VersionedAndRidCheckedCompositeToken.ToCosmosElement( new VersionedAndRidCheckedCompositeToken( VersionedAndRidCheckedCompositeToken.Version.V2, innerContinuationToken, await this.documentContainer.GetResourceIdentifierAsync(cancellationToken))).ToString(); } responseMessage.Headers.ContinuationToken = continuationToken; responseMessage.Headers.RequestCharge = changeFeedPage.RequestCharge; responseMessage.Headers.ActivityId = changeFeedPage.ActivityId; return(responseMessage); }