public async Task ChangeFeedIteratorCore_ReadAll() { int totalCount = 0; int firstRunTotal = 25; int batchSize = 25; await this.CreateRandomItems(this.LargerContainer, batchSize, randomPartitionKey : true); ContainerInternal itemsCore = this.LargerContainer; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( changeFeedRequestOptions: new ChangeFeedRequestOptions() { From = ChangeFeedRequestOptions.StartFrom.CreateFromBeginning(), }) as ChangeFeedIteratorCore; string continuation = null; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; } continuation = responseMessage.ContinuationToken; } } Assert.AreEqual(firstRunTotal, totalCount); int expectedFinalCount = 50; // Insert another batch of 25 and use the last FeedToken from the first cycle await this.CreateRandomItems(this.LargerContainer, batchSize, randomPartitionKey : true); ChangeFeedIteratorCore setIteratorNew = itemsCore.GetChangeFeedStreamIterator( changeFeedRequestOptions: new ChangeFeedRequestOptions() { From = ChangeFeedRequestOptions.StartFrom.CreateFromContinuation(continuation), }) as ChangeFeedIteratorCore; while (setIteratorNew.HasMoreResults) { using (ResponseMessage responseMessage = await setIteratorNew.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; } } } Assert.AreEqual(expectedFinalCount, totalCount); }
public async Task ChangeFeedIteratorCore_WithMaxItemCount() { ContainerInternal itemsCore = await this.InitializeContainerAsync(); await this.CreateRandomItems(itemsCore, 2, randomPartitionKey : true); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental, changeFeedRequestOptions: new ChangeFeedRequestOptions() { PageSizeHint = 1, }) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (!responseMessage.IsSuccessStatusCode) { break; } Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; if (response.Count > 0) { Assert.AreEqual(1, response.Count); return; } } } Assert.Fail("Found no batch with size 1"); }
public async Task ChangeFeedIteratorCore_BreathFirst() { int expected = 500; List <CompositeContinuationToken> previousToken = null; await this.CreateRandomItems(this.LargerContainer, expected, randomPartitionKey : true); ContainerInternal itemsCore = this.LargerContainer; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), new ChangeFeedRequestOptions() { PageSizeHint = 1, }) as ChangeFeedIteratorCore; while (true) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { Assert.IsTrue(FeedRangeCompositeContinuation.TryParse(responseMessage.ContinuationToken, out FeedRangeContinuation continuation)); FeedRangeCompositeContinuation compositeContinuation = continuation as FeedRangeCompositeContinuation; List <CompositeContinuationToken> deserializedToken = compositeContinuation.CompositeContinuationTokens.ToList(); if (previousToken != null) { // Verify that the token, even though it yielded results, it moved to a new range Assert.AreNotEqual(previousToken[0].Range.Min, deserializedToken[0].Range.Min); Assert.AreNotEqual(previousToken[0].Range.Max, deserializedToken[0].Range.Max); break; } previousToken = deserializedToken; } } }
public async Task ChangeFeedIteratorCore_EmptyBeginning() { int totalCount = 0; int expectedDocuments = 5; bool createdDocuments = false; ContainerInternal itemsCore = this.Container; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning()) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults || (createdDocuments && totalCount == 0)) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; } else { if (!createdDocuments) { await this.CreateRandomItems(this.Container, expectedDocuments, randomPartitionKey : true); createdDocuments = true; } } } } Assert.AreEqual(expectedDocuments, totalCount); }
public async Task ChangeFeedIteratorCore_StartTime() { int totalCount = 0; int batchSize = 25; await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true); await Task.Delay(1000); DateTime now = DateTime.UtcNow; await Task.Delay(1000); await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true); ContainerInternal itemsCore = this.Container; FeedIterator feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Time(now)); while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; } } } Assert.AreEqual(totalCount, batchSize); }
public async Task ChangeFeedIteratorCore_WithMaxItemCount() { await this.CreateRandomItems(this.Container, 2, randomPartitionKey : true); ContainerInternal itemsCore = this.Container; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(changeFeedRequestOptions: new ChangeFeedRequestOptions() { MaxItemCount = 1, StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; if (response.Count > 0) { Assert.AreEqual(1, response.Count); return; } } } } Assert.Fail("Found no batch with size 1"); }
public async Task ChangeFeedIteratorCore_NoFetchNext() { ContainerInternal itemsCore = await this.InitializeLargeContainerAsync(); int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; int expected = 25; int iterations = 0; await this.CreateRandomItems(itemsCore, expected, randomPartitionKey : true); string continuation = null; int count = 0; while (true) { ChangeFeedStartFrom startFrom; if (continuation == null) { startFrom = ChangeFeedStartFrom.Beginning(); } else { startFrom = ChangeFeedStartFrom.ContinuationToken(continuation); } ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(startFrom, ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; count += response.Count; } else { if (responseMessage.StatusCode != HttpStatusCode.NotModified) { Assert.Fail(responseMessage.ErrorMessage); } } continuation = responseMessage.ContinuationToken; } if (count.Equals(expected)) { break; } if (iterations++ > pkRangesCount) { Assert.Fail("" + "Feed does not contain all elements even after looping through PK ranges. " + "Either the continuation is not moving forward or there is some state problem."); } } }
public async Task GetFeedRangesAsync_AllowsParallelProcessing() { ContainerInternal itemsCore = await this.InitializeLargeContainerAsync(); int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; IEnumerable <FeedRange> tokens = await itemsCore.GetFeedRangesAsync(); Assert.IsTrue(pkRangesCount > 1, "Should have created a multi partition container."); Assert.AreEqual(pkRangesCount, tokens.Count()); int totalDocuments = 200; await this.CreateRandomItems(itemsCore, totalDocuments, randomPartitionKey : true); List <Task <int> > tasks = tokens.Select(token => Task.Run(async() => { int count = 0; ChangeFeedIteratorCore iteratorForToken = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(token), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; while (true) { using (ResponseMessage responseMessage = await iteratorForToken.ReadNextAsync(this.cancellationToken)) { if (!responseMessage.IsSuccessStatusCode) { break; } Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; count += response.Count; } } return(count); })).ToList(); await Task.WhenAll(tasks); int documentsRead = 0; foreach (Task <int> task in tasks) { documentsRead += task.Result; } Assert.AreEqual(totalDocuments, documentsRead); }
public async Task ChangeFeedIteratorCore_BreathFirst() { int expected = 500; CosmosObject previousToken = null; ContainerInternal itemsCore = await this.InitializeLargeContainerAsync(); await this.CreateRandomItems(itemsCore, expected, randomPartitionKey : true); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental, new ChangeFeedRequestOptions() { PageSizeHint = 1, }) as ChangeFeedIteratorCore; while (true) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { CosmosObject cosmosObject = CosmosObject.Parse(responseMessage.ContinuationToken); if (!cosmosObject.TryGetValue("Continuation", out CosmosArray cosmosArray)) { Assert.Fail(); throw new Exception(); } CosmosObject currentToken = (CosmosObject)cosmosArray[0]; if (previousToken != null) { // Verify that the token, even though it yielded results, it moved to a new range Assert.AreNotEqual(previousToken, currentToken); break; } previousToken = currentToken; if (responseMessage.StatusCode == HttpStatusCode.NotModified) { break; } } } }
public async Task ChangeFeedIteratorCore_NoFetchNext() { int pkRangesCount = (await this.LargerContainer.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(this.LargerContainer.LinkUri)).Count; int expected = 25; int iterations = 0; await this.CreateRandomItems(this.LargerContainer, expected, randomPartitionKey : true); ContainerInternal itemsCore = this.LargerContainer; string continuation = null; int count = 0; while (true) { ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(continuationToken: continuation, changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; count += response.Count; } continuation = responseMessage.ContinuationToken; } if (count.Equals(expected)) { break; } if (iterations++ > pkRangesCount) { Assert.Fail("Feed does not contain all elements even after looping through PK ranges. Either the continuation is not moving forward or there is some state problem."); } } }
public async Task ChangeFeedIteratorCore_CannotMixTokensFromOtherContainers() { ContainerInternal oneContainer = await this.InitializeContainerAsync(); ContainerInternal otherContainer = await this.InitializeContainerAsync(); IReadOnlyList <FeedRange> tokens = await oneContainer.GetFeedRangesAsync(); FeedIterator iterator = oneContainer.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(tokens[0]), ChangeFeedMode.Incremental); ResponseMessage responseMessage = await iterator.ReadNextAsync(); iterator = otherContainer.GetChangeFeedStreamIterator( ChangeFeedStartFrom.ContinuationToken(responseMessage.ContinuationToken), ChangeFeedMode.Incremental); responseMessage = await iterator.ReadNextAsync(); Assert.IsNotNull(responseMessage.CosmosException); Assert.AreEqual(HttpStatusCode.BadRequest, responseMessage.StatusCode); }
public async Task ChangeFeedIteratorCore_PartitionKey_ReadAll() { int totalCount = 0; int firstRunTotal = 25; int batchSize = 25; string pkToRead = "pkToRead"; string otherPK = "otherPK"; ContainerInternal itemsCore = await this.InitializeContainerAsync(); for (int i = 0; i < batchSize; i++) { await itemsCore.CreateItemAsync(ToDoActivity.CreateRandomToDoActivity(pk: pkToRead)); } for (int i = 0; i < batchSize; i++) { await itemsCore.CreateItemAsync(ToDoActivity.CreateRandomToDoActivity(pk: otherPK)); } ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning( FeedRange.FromPartitionKey( new PartitionKey(pkToRead))), ChangeFeedMode.Incremental, new ChangeFeedRequestOptions() { PageSizeHint = 1, }) as ChangeFeedIteratorCore; string continuation = null; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (!responseMessage.IsSuccessStatusCode) { continuation = responseMessage.ContinuationToken; break; } Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; foreach (ToDoActivity toDoActivity in response) { Assert.AreEqual(pkToRead, toDoActivity.pk); } } } Assert.AreEqual(firstRunTotal, totalCount); int expectedFinalCount = 50; // Insert another batch of 25 and use the last FeedToken from the first cycle for (int i = 0; i < batchSize; i++) { await itemsCore.CreateItemAsync(ToDoActivity.CreateRandomToDoActivity(pk: pkToRead)); } ChangeFeedIteratorCore setIteratorNew = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.ContinuationToken(continuation), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; while (setIteratorNew.HasMoreResults) { using (ResponseMessage responseMessage = await setIteratorNew.ReadNextAsync(this.cancellationToken)) { if (!responseMessage.IsSuccessStatusCode) { break; } Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; foreach (ToDoActivity toDoActivity in response) { Assert.AreEqual(pkToRead, toDoActivity.pk); } } } Assert.AreEqual(expectedFinalCount, totalCount); }
public async Task ChangeFeed_FeedRange_FromV0Token() { ContainerResponse largerContainer = await this.database.CreateContainerAsync( new ContainerProperties(id : Guid.NewGuid().ToString(), partitionKeyPath : "/pk"), throughput : 20000, cancellationToken : this.cancellationToken); ContainerInternal container = (ContainerInlineCore)largerContainer; int expected = 100; int count = 0; await this.CreateRandomItems((ContainerCore)container, expected, randomPartitionKey : true); IReadOnlyList <FeedRange> feedRanges = await container.GetFeedRangesAsync(); List <string> continuations = new List <string>(); // First do one request to construct the old model information based on Etag foreach (FeedRange feedRange in feedRanges) { IEnumerable <string> pkRangeIds = await container.GetPartitionKeyRangesAsync(feedRange); ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { PageSizeHint = 1 }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator( changeFeedStartFrom: ChangeFeedStartFrom.Beginning(feedRange), changeFeedMode: ChangeFeedMode.Incremental, changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; ResponseMessage firstResponse = await feedIterator.ReadNextAsync(); // Construct the continuation's range, using PKRangeId + ETag List <dynamic> ct = new List <dynamic>() { new { FeedRange = new { type = "Physical Partition Key Range Id", value = pkRangeIds.First() }, State = new { type = "continuation", value = JObject.Parse(firstResponse.ContinuationToken)["Continuation"][0]["State"]["value"].ToString() } } }; if (firstResponse.Content != null) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(firstResponse.Content).Data; count += response.Count; } // Extract Etag and manually construct the continuation dynamic oldContinuation = new { V = 2, Rid = await container.GetCachedRIDAsync(cancellationToken : this.cancellationToken), Continuation = ct }; continuations.Add(JsonConvert.SerializeObject(oldContinuation)); } // Now start the new iterators with the constructed continuations from migration foreach (string continuation in continuations) { ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { PageSizeHint = 100, }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator( changeFeedStartFrom: ChangeFeedStartFrom.ContinuationToken(continuation), changeFeedMode: ChangeFeedMode.Incremental, changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; ResponseMessage firstResponse = await feedIterator.ReadNextAsync(); if (firstResponse.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(firstResponse.Content).Data; count += response.Count; string migratedContinuation = firstResponse.ContinuationToken; TryCatch <CosmosElement> monadicParsedToken = CosmosElement.Monadic.Parse(migratedContinuation); Assert.IsFalse(monadicParsedToken.Failed); TryCatch <VersionedAndRidCheckedCompositeToken> monadicVersionedToken = VersionedAndRidCheckedCompositeToken .MonadicCreateFromCosmosElement(monadicParsedToken.Result); Assert.IsFalse(monadicVersionedToken.Failed); VersionedAndRidCheckedCompositeToken versionedAndRidCheckedCompositeToken = monadicVersionedToken.Result; Assert.AreEqual(VersionedAndRidCheckedCompositeToken.Version.V2, versionedAndRidCheckedCompositeToken.VersionNumber); } } Assert.AreEqual(expected, count); }
public async Task ChangeFeedIteratorCore_PartitionKey_ReadAll() { int totalCount = 0; int firstRunTotal = 25; int batchSize = 25; string pkToRead = "pkToRead"; string otherPK = "otherPK"; for (int i = 0; i < batchSize; i++) { await this.Container.CreateItemAsync(this.CreateRandomToDoActivity(pkToRead)); } for (int i = 0; i < batchSize; i++) { await this.Container.CreateItemAsync(this.CreateRandomToDoActivity(otherPK)); } ContainerInternal itemsCore = this.Container; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(new PartitionKey(pkToRead), changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; string continuation = null; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; foreach (ToDoActivity toDoActivity in response) { Assert.AreEqual(pkToRead, toDoActivity.status); } } continuation = responseMessage.ContinuationToken; } } Assert.AreEqual(firstRunTotal, totalCount); int expectedFinalCount = 50; // Insert another batch of 25 and use the last FeedToken from the first cycle for (int i = 0; i < batchSize; i++) { await this.Container.CreateItemAsync(this.CreateRandomToDoActivity(pkToRead)); } ChangeFeedIteratorCore setIteratorNew = itemsCore.GetChangeFeedStreamIterator(continuationToken: continuation, changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (setIteratorNew.HasMoreResults) { using (ResponseMessage responseMessage = await setIteratorNew.ReadNextAsync(this.cancellationToken)) { if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; foreach (ToDoActivity toDoActivity in response) { Assert.AreEqual(pkToRead, toDoActivity.status); } } } } Assert.AreEqual(expectedFinalCount, totalCount); }
public async Task ChangeFeed_FeedRange_FromV0Token() { ContainerResponse largerContainer = await this.database.CreateContainerAsync( new ContainerProperties(id : Guid.NewGuid().ToString(), partitionKeyPath : "/status"), throughput : 20000, cancellationToken : this.cancellationToken); ContainerInternal container = (ContainerInlineCore)largerContainer; int expected = 100; int count = 0; await this.CreateRandomItems((ContainerCore)container, expected, randomPartitionKey : true); IReadOnlyList <FeedRange> feedRanges = await container.GetFeedRangesAsync(); List <string> continuations = new List <string>(); // First do one request to construct the old model information based on Etag foreach (FeedRange feedRange in feedRanges) { IEnumerable <string> pkRangeIds = await container.GetPartitionKeyRangesAsync(feedRange); ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { PageSizeHint = 1 }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator( changeFeedStartFrom: ChangeFeedStartFrom.Beginning(feedRange), changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; ResponseMessage firstResponse = await feedIterator.ReadNextAsync(); FeedRangeEpk FeedRangeEpk = feedRange as FeedRangeEpk; // Construct the continuation's range, using PKRangeId + ETag List <dynamic> ct = new List <dynamic>() { new { min = FeedRangeEpk.Range.Min, max = FeedRangeEpk.Range.Max, token = (string)null } }; // Extract Etag and manually construct the continuation dynamic oldContinuation = new { V = 0, Rid = await container.GetCachedRIDAsync(cancellationToken : this.cancellationToken), Continuation = ct }; continuations.Add(JsonConvert.SerializeObject(oldContinuation)); } // Now start the new iterators with the constructed continuations from migration foreach (string continuation in continuations) { ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { PageSizeHint = 100, EmitOldContinuationToken = true, }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator( changeFeedStartFrom: ChangeFeedStartFrom.ContinuationToken(continuation), changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; ResponseMessage firstResponse = await feedIterator.ReadNextAsync(); if (firstResponse.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(firstResponse.Content).Data; count += response.Count; string migratedContinuation = firstResponse.ContinuationToken; Assert.IsTrue(FeedRangeContinuation.TryParse(migratedContinuation, out FeedRangeContinuation feedRangeContinuation)); Assert.IsTrue(feedRangeContinuation.FeedRange is FeedRangeEpk); } } Assert.AreEqual(expected, count); }
public async Task TestCancellationTokenAsync() { CancellationTokenRequestHandler cancellationTokenHandler = new CancellationTokenRequestHandler(); ContainerInternal itemsCore = await this.InitializeContainerAsync(); await this.CreateRandomItems(itemsCore, 100, randomPartitionKey : true); // Inject validating handler RequestHandler currentInnerHandler = this.cosmosClient.RequestHandler.InnerHandler; this.cosmosClient.RequestHandler.InnerHandler = cancellationTokenHandler; cancellationTokenHandler.InnerHandler = currentInnerHandler; { // Test to see if the token flows to the pipeline CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; await feedIterator.ReadNextAsync(cancellationTokenSource.Token); Assert.AreEqual(cancellationTokenSource.Token, cancellationTokenHandler.LastUsedToken, "The token passed did not reach the pipeline"); } // See if cancellation token is honored for first request try { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.Cancel(); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; await feedIterator.ReadNextAsync(cancellationTokenSource.Token); Assert.Fail("Expected exception."); } catch (OperationCanceledException) { } // See if cancellation token is honored for second request try { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.Cancel(); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; await feedIterator.ReadNextAsync(); await feedIterator.ReadNextAsync(cancellationTokenSource.Token); Assert.Fail("Expected exception."); } catch (OperationCanceledException) { } // See if cancellation token is honored mid draining try { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental) as ChangeFeedIteratorCore; await feedIterator.ReadNextAsync(cancellationTokenSource.Token); cancellationTokenSource.Cancel(); await feedIterator.ReadNextAsync(cancellationTokenSource.Token); Assert.Fail("Expected exception."); } catch (OperationCanceledException) { } }