public FeedRangeCompositeContinuation( string containerRid, FeedRangeInternal feedRange, IReadOnlyList <Documents.Routing.Range <string> > ranges, string continuation = null) : this(containerRid, feedRange) { if (ranges == null) { throw new ArgumentNullException(nameof(ranges)); } if (ranges.Count == 0) { throw new ArgumentOutOfRangeException(nameof(ranges)); } foreach (Documents.Routing.Range <string> range in ranges) { this.CompositeContinuationTokens.Enqueue( FeedRangeCompositeContinuation.CreateCompositeContinuationTokenForRange( range.Min, range.Max, continuation)); } this.CurrentToken = this.CompositeContinuationTokens.Peek(); }
public static FeedRangeIteratorCore Create( ContainerCore containerCore, FeedRangeInternal feedRangeInternal, string continuation, QueryRequestOptions options) { if (!string.IsNullOrEmpty(continuation)) { if (FeedRangeContinuation.TryParse(continuation, out FeedRangeContinuation feedRangeContinuation)) { return(new FeedRangeIteratorCore(containerCore, feedRangeContinuation, options)); } // Backward compatible with old format feedRangeInternal = FeedRangeEPK.ForCompleteRange(); feedRangeContinuation = new FeedRangeCompositeContinuation( string.Empty, feedRangeInternal, new List <Documents.Routing.Range <string> >() { new Documents.Routing.Range <string>( Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMinInclusive: true, isMaxInclusive: false) }, continuation); return(new FeedRangeIteratorCore(containerCore, feedRangeContinuation, options)); } feedRangeInternal = feedRangeInternal ?? FeedRangeEPK.ForCompleteRange(); return(new FeedRangeIteratorCore(containerCore, feedRangeInternal, options)); }
public void Visit(FeedRangeCompositeContinuation feedRangeCompositeContinuation) { // In case EPK has already been set by compute if (!this.request.Properties.ContainsKey(HandlerConstants.StartEpkString)) { this.request.Properties[HandlerConstants.StartEpkString] = feedRangeCompositeContinuation.CurrentToken.Range.Min; this.request.Properties[HandlerConstants.EndEpkString] = feedRangeCompositeContinuation.CurrentToken.Range.Max; } this.fillContinuation(this.request, feedRangeCompositeContinuation.GetContinuation()); }
public static bool TryParse( string toStringValue, out FeedRangeContinuation parsedToken) { if (!FeedRangeCompositeContinuation.TryParse(toStringValue, out parsedToken)) { parsedToken = null; return(false); } return(true); }
private void CreateChildRanges(IReadOnlyList <Documents.PartitionKeyRange> keyRanges) { if (keyRanges == null) { throw new ArgumentNullException(nameof(keyRanges)); } // Update current Documents.PartitionKeyRange firstRange = keyRanges[0]; this.CurrentToken.Range = new Documents.Routing.Range <string>(firstRange.MinInclusive, firstRange.MaxExclusive, true, false); // Add children foreach (Documents.PartitionKeyRange keyRange in keyRanges.Skip(1)) { this.CompositeContinuationTokens.Enqueue( FeedRangeCompositeContinuation.CreateCompositeContinuationTokenForRange( keyRange.MinInclusive, keyRange.MaxExclusive, this.CurrentToken.Token)); } }
private void CreateChildRanges(IReadOnlyList <Documents.PartitionKeyRange> keyRanges) { if (keyRanges == null) { throw new ArgumentNullException(nameof(keyRanges)); } // Update current Documents.PartitionKeyRange firstRange = keyRanges[0]; this.CurrentToken.Range = new Documents.Routing.Range <string>(firstRange.MinInclusive, firstRange.MaxExclusive, true, false); if (FeedRangeCompositeContinuation.TryParseAsCompositeContinuationToken( this.CurrentToken.Token, out CompositeContinuationToken continuationAsComposite)) { // Update the internal composite continuation continuationAsComposite.Range = this.CurrentToken.Range; this.CurrentToken.Token = JsonConvert.SerializeObject(continuationAsComposite); // Add children foreach (Documents.PartitionKeyRange keyRange in keyRanges.Skip(1)) { continuationAsComposite.Range = keyRange.ToRange(); this.CompositeContinuationTokens.Enqueue( FeedRangeCompositeContinuation.CreateCompositeContinuationTokenForRange( keyRange.MinInclusive, keyRange.MaxExclusive, JsonConvert.SerializeObject(continuationAsComposite))); } } else { // Add children foreach (Documents.PartitionKeyRange keyRange in keyRanges.Skip(1)) { this.CompositeContinuationTokens.Enqueue( FeedRangeCompositeContinuation.CreateCompositeContinuationTokenForRange( keyRange.MinInclusive, keyRange.MaxExclusive, this.CurrentToken.Token)); } } }
/// <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,
public ReadFeedIteratorCore( IDocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, string continuationToken, int pageSize, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(continuationToken)) { bool isNewArrayFormat = (continuationToken.Length >= 2) && (continuationToken[0] == '[') && (continuationToken[continuationToken.Length - 1] == ']'); if (!isNewArrayFormat) { // One of the two older formats if (!FeedRangeContinuation.TryParse(continuationToken, out FeedRangeContinuation feedRangeContinuation)) { // Backward compatible with old format feedRangeContinuation = new FeedRangeCompositeContinuation( containerRid: string.Empty, FeedRangeEpk.FullRange, new List <Documents.Routing.Range <string> >() { new Documents.Routing.Range <string>( Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMinInclusive: true, isMaxInclusive: false) }, continuationToken); } // need to massage it a little string oldContinuationFormat = feedRangeContinuation.ToString(); CosmosObject cosmosObject = CosmosObject.Parse(oldContinuationFormat); CosmosArray continuations = (CosmosArray)cosmosObject["Continuation"]; List <CosmosElement> readFeedContinuationTokens = new List <CosmosElement>(); foreach (CosmosElement continuation in continuations) { CosmosObject continuationObject = (CosmosObject)continuation; CosmosObject rangeObject = (CosmosObject)continuationObject["range"]; string min = ((CosmosString)rangeObject["min"]).Value; string max = ((CosmosString)rangeObject["max"]).Value; CosmosElement token = CosmosElement.Parse(((CosmosString)continuationObject["token"]).Value); FeedRangeInternal feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false)); ReadFeedState state = new ReadFeedState(token); ReadFeedContinuationToken readFeedContinuationToken = new ReadFeedContinuationToken(feedRange, state); readFeedContinuationTokens.Add(ReadFeedContinuationToken.ToCosmosElement(readFeedContinuationToken)); } CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(readFeedContinuationTokens); continuationToken = cosmosArrayContinuationTokens.ToString(); } } this.monadicEnumerator = CrossPartitionReadFeedAsyncEnumerator.MonadicCreate( documentContainer, queryRequestOptions, continuationToken: continuationToken, pageSize, cancellationToken); this.hasMoreResults = true; }