Exemplo n.º 1
0
        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 IAsyncEnumerator <TryCatch <ReadFeedPage> > GetAsyncEnumerator(CancellationToken cancellationToken = default)
        {
            CrossFeedRangeState <ReadFeedState>   innerState      = new CrossFeedRangeState <ReadFeedState>(this.state.FeedRangeStates);
            CrossPartitionReadFeedAsyncEnumerator innerEnumerator = CrossPartitionReadFeedAsyncEnumerator.Create(
                this.documentContainer,
                innerState,
                this.readFeedPaginationOptions,
                cancellationToken);

            return(new ReadFeedCrossFeedRangeAsyncEnumerator(innerEnumerator));
        }
        public ReadFeedIteratorCore(
            IDocumentContainer documentContainer,
            string continuationToken,
            ReadFeedPaginationOptions readFeedPaginationOptions,
            QueryRequestOptions queryRequestOptions,
            CancellationToken cancellationToken)
        {
            this.queryRequestOptions = queryRequestOptions;
            readFeedPaginationOptions ??= ReadFeedPaginationOptions.Default;

            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
                    List <CosmosElement> feedRangeStates = new List <CosmosElement>();
                    string oldContinuationFormat         = feedRangeContinuation.ToString();
                    if (feedRangeContinuation.FeedRange is FeedRangePartitionKey feedRangePartitionKey)
                    {
                        CosmosObject cosmosObject  = CosmosObject.Parse(oldContinuationFormat);
                        CosmosArray  continuations = (CosmosArray)cosmosObject["Continuation"];
                        if (continuations.Count != 1)
                        {
                            throw new InvalidOperationException("Expected only one continuation for partition key queries");
                        }

                        CosmosElement continuation       = continuations[0];
                        CosmosObject  continuationObject = (CosmosObject)continuation;
                        CosmosElement token = continuationObject["token"];
                        ReadFeedState state;
                        if (token is CosmosNull)
                        {
                            state = ReadFeedState.Beginning();
                        }
                        else
                        {
                            CosmosString tokenAsString = (CosmosString)token;
                            state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value));
                        }

                        FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRangePartitionKey, state);
                        feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState));
                    }
                    else
                    {
                        CosmosObject cosmosObject  = CosmosObject.Parse(oldContinuationFormat);
                        CosmosArray  continuations = (CosmosArray)cosmosObject["Continuation"];

                        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 = continuationObject["token"];

                            FeedRangeInternal feedRange = new FeedRangeEpk(new Documents.Routing.Range <string>(min, max, isMinInclusive: true, isMaxInclusive: false));
                            ReadFeedState     state;
                            if (token is CosmosNull)
                            {
                                state = ReadFeedState.Beginning();
                            }
                            else
                            {
                                CosmosString tokenAsString = (CosmosString)token;
                                state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value));
                            }

                            FeedRangeState <ReadFeedState> feedRangeState = new FeedRangeState <ReadFeedState>(feedRange, state);
                            feedRangeStates.Add(ReadFeedFeedRangeStateSerializer.ToCosmosElement(feedRangeState));
                        }
                    }

                    CosmosArray cosmosArrayContinuationTokens = CosmosArray.Create(feedRangeStates);
                    continuationToken = cosmosArrayContinuationTokens.ToString();
                }
            }

            TryCatch <ReadFeedCrossFeedRangeState> monadicReadFeedState;

            if (continuationToken == null)
            {
                FeedRange feedRange;
                if ((this.queryRequestOptions != null) && this.queryRequestOptions.PartitionKey.HasValue)
                {
                    feedRange = new FeedRangePartitionKey(this.queryRequestOptions.PartitionKey.Value);
                }
                else if ((this.queryRequestOptions != null) && (this.queryRequestOptions.FeedRange != null))
                {
                    feedRange = this.queryRequestOptions.FeedRange;
                }
                else
                {
                    feedRange = FeedRangeEpk.FullRange;
                }

                monadicReadFeedState = TryCatch <ReadFeedCrossFeedRangeState> .FromResult(ReadFeedCrossFeedRangeState.CreateFromBeginning(feedRange));
            }
            else
            {
                monadicReadFeedState = ReadFeedCrossFeedRangeState.Monadic.Parse(continuationToken);
            }

            if (monadicReadFeedState.Failed)
            {
                this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromException(monadicReadFeedState.Exception);
            }
            else
            {
                this.monadicEnumerator = TryCatch <CrossPartitionReadFeedAsyncEnumerator> .FromResult(
                    CrossPartitionReadFeedAsyncEnumerator.Create(
                        documentContainer,
                        new CrossFeedRangeState <ReadFeedState>(monadicReadFeedState.Result.FeedRangeStates),
                        readFeedPaginationOptions,
                        cancellationToken));
            }

            this.hasMoreResults = true;
        }
        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);
        }