public async Task SerializeAndDeserializeContinuationToken()
        {
            int batchSize = 25;

            (int totalCount, ChangeFeedCrossFeedRangeState state)countAndState;
            IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                ChangeFeedCrossFeedRangeState.CreateFromBeginning(),
                ChangeFeedMode.Incremental);

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            countAndState = await PartialDrainAsync(asyncEnumerable);

            Assert.AreEqual(batchSize, countAndState.totalCount);

            // Serialize the state and send it over the wire for your user to resume execution.
            string continuationToken = countAndState.state.ToString();

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            // Deserialize the state that the user came back with to resume from.
            ChangeFeedCrossFeedRangeState state = ChangeFeedCrossFeedRangeState.Parse(continuationToken);

            asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(state, ChangeFeedMode.Incremental);
            countAndState   = await PartialDrainAsync(asyncEnumerable);

            Assert.AreEqual(batchSize, countAndState.totalCount);
        }
Exemple #2
0
        public async Task TestCancellationToken()
        {
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            cancellationTokenSource.Cancel();

            IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                ChangeFeedCrossFeedRangeState.CreateFromBeginning());

            await foreach (TryCatch <ChangeFeedPage> monadicPage in asyncEnumerable.WithCancellation(cancellationTokenSource.Token))
            {
                monadicPage.ThrowIfFailed();
            }
        }
        public async Task TestContentSerializationOptions()
        {
            {
                // Native format
                IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                    ChangeFeedCrossFeedRangeState.CreateFromBeginning(),
                    ChangeFeedMode.Incremental,
                    new ChangeFeedRequestOptions()
                {
                    JsonSerializationFormatOptions = JsonSerializationFormatOptions.Create(JsonSerializationFormat.Binary)
                });
                await foreach (TryCatch <ChangeFeedPage> monadicPage in asyncEnumerable)
                {
                    monadicPage.ThrowIfFailed();

                    if (monadicPage.Result.NotModified)
                    {
                        break;
                    }
                }
            }

            {
                // Custom format
                IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                    ChangeFeedCrossFeedRangeState.CreateFromBeginning(),
                    ChangeFeedMode.Incremental,
                    new ChangeFeedRequestOptions()
                {
                    JsonSerializationFormatOptions = JsonSerializationFormatOptions.Create(
                        JsonSerializationFormat.Binary,
                        (content) => JsonNavigator.Create(content))
                });
                await foreach (TryCatch <ChangeFeedPage> monadicPage in asyncEnumerable)
                {
                    monadicPage.ThrowIfFailed();

                    if (monadicPage.Result.NotModified)
                    {
                        break;
                    }
                }
            }
        }
        public async Task TestScaleUpAndScaleDown()
        {
            int batchSize = 25;

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            // Start draining as 1 iterator
            IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                ChangeFeedCrossFeedRangeState.CreateFromBeginning(),
                ChangeFeedMode.Incremental);

            (int totalCount, ChangeFeedCrossFeedRangeState state) = await PartialDrainAsync(asyncEnumerable);

            Assert.AreEqual(batchSize, totalCount);

            // Continue draining as two iterators
            if (!state.TrySplit(out ChangeFeedCrossFeedRangeState first, out ChangeFeedCrossFeedRangeState second))
            {
                Assert.Fail("Failed to split");
            }

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            IAsyncEnumerable <TryCatch <ChangeFeedPage> > leftEnumerable = this.Container.GetChangeFeedAsyncEnumerable(first, ChangeFeedMode.Incremental);

            (int leftTotalCount, ChangeFeedCrossFeedRangeState leftResumeState) = await PartialDrainAsync(leftEnumerable);

            IAsyncEnumerable <TryCatch <ChangeFeedPage> > rightEnumerable = this.Container.GetChangeFeedAsyncEnumerable(second, ChangeFeedMode.Incremental);

            (int rightTotalCount, ChangeFeedCrossFeedRangeState rightResumeState) = await PartialDrainAsync(rightEnumerable);

            Assert.AreEqual(batchSize, leftTotalCount + rightTotalCount);

            // Finish draining again as a single enumerator
            ChangeFeedCrossFeedRangeState mergedState = leftResumeState.Merge(rightResumeState);

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            IAsyncEnumerable <TryCatch <ChangeFeedPage> > mergedEnumerable = this.Container.GetChangeFeedAsyncEnumerable(mergedState, ChangeFeedMode.Incremental);

            (int mergedTotalCount, ChangeFeedCrossFeedRangeState _) = await PartialDrainAsync(mergedEnumerable);

            Assert.AreEqual(batchSize, mergedTotalCount);
        }
Exemple #5
0
        public async Task TestCustomRequestOptionsAsync()
        {
            IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                ChangeFeedCrossFeedRangeState.CreateFromBeginning(),
                ChangeFeedMode.Incremental,
                new ChangeFeedRequestOptions()
            {
                Properties = new Dictionary <string, object>()
                {
                    { HttpConstants.HttpHeaders.SessionToken, "AnInvalidSessionToken" }
                }
            });

            await foreach (TryCatch <ChangeFeedPage> monadicPage in asyncEnumerable)
            {
                Assert.IsTrue(monadicPage.Failed);
                Assert.AreEqual(((CosmosException)monadicPage.InnerMostException).StatusCode, System.Net.HttpStatusCode.BadRequest);
                break;
            }
        }
Exemple #6
0
        public async Task StartFromBeginning()
        {
            int batchSize = 25;

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            (int totalCount, ChangeFeedCrossFeedRangeState state)countAndState;
            IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(
                ChangeFeedCrossFeedRangeState.CreateFromBeginning());

            countAndState = await PartialDrainAsync(asyncEnumerable);

            Assert.AreEqual(batchSize, countAndState.totalCount);

            // Insert another batch of 25 and use the state from the first cycle
            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(countAndState.state);
            countAndState   = await PartialDrainAsync(asyncEnumerable);

            Assert.AreEqual(batchSize, countAndState.totalCount);
        }
        public async Task ParallelizeAcrossFeedRanges()
        {
            int batchSize = 25;

            await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true);

            // Create one start state for each physical partition.
            List <ChangeFeedCrossFeedRangeState> startStates = new List <ChangeFeedCrossFeedRangeState>();
            IReadOnlyList <FeedRange>            feedRanges  = await this.Container.GetFeedRangesAsync();

            foreach (FeedRange feedRange in feedRanges)
            {
                startStates.Add(ChangeFeedCrossFeedRangeState.CreateFromBeginning(feedRange));
            }

            // Create an independant enumerable for each of those start states.
            List <IAsyncEnumerable <TryCatch <ChangeFeedPage> > > asyncEnumerables = new List <IAsyncEnumerable <TryCatch <ChangeFeedPage> > >();

            foreach (ChangeFeedCrossFeedRangeState state in startStates)
            {
                IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable = this.Container.GetChangeFeedAsyncEnumerable(state, ChangeFeedMode.Incremental);
                asyncEnumerables.Add(asyncEnumerable);
            }

            int totalCount = 0;

            foreach (IAsyncEnumerable <TryCatch <ChangeFeedPage> > asyncEnumerable in asyncEnumerables)
            {
                // This part can be done in parallel on the same machine or on different machines,
                // since they are independant enumerables.
                (int totalCount, ChangeFeedCrossFeedRangeState state)countAndState = await PartialDrainAsync(asyncEnumerable);

                totalCount += countAndState.totalCount;
            }

            Assert.AreEqual(batchSize, totalCount);
        }