public async Task ChangeFeedIteratorCore_ReadNextAsync() { int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore( documentContainer, new ChangeFeedRequestOptions(), ChangeFeedStartFrom.Beginning()); int count = 0; while (changeFeedIteratorCore.HasMoreResults) { ResponseMessage responseMessage = await changeFeedIteratorCore.ReadNextAsync(); if (responseMessage.StatusCode == HttpStatusCode.NotModified) { break; } count += GetChanges(responseMessage.Content).Count; } Assert.AreEqual(numItems, count); }
public async Task ChangeFeedIteratorCore_HandlesSplitsThroughPipeline() { int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore( documentContainer, new ChangeFeedRequestOptions(), ChangeFeedStartFrom.Beginning()); int seed = new Random().Next(); Random random = new Random(seed); int count = 0; while (changeFeedIteratorCore.HasMoreResults) { ResponseMessage responseMessage = await changeFeedIteratorCore.ReadNextAsync(); if (responseMessage.StatusCode == HttpStatusCode.NotModified) { break; } count += GetChanges(responseMessage.Content).Count; await documentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken : default); IReadOnlyList <FeedRangeInternal> ranges = await documentContainer.GetFeedRangesAsync(trace : NoOpTrace.Singleton, cancellationToken : default);
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(changeFeedRequestOptions: new ChangeFeedRequestOptions() { MaxItemCount = 1, From = ChangeFeedRequestOptions.StartFrom.CreateFromBeginning(), }) 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_BreathFirst() { int expected = 500; List <CompositeContinuationToken> previousToken = null; await this.CreateRandomItems(this.LargerContainer, expected, randomPartitionKey : true); ContainerCore itemsCore = this.LargerContainer; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime(), MaxItemCount = 1 }) as ChangeFeedIteratorCore; while (true) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { FeedTokenEPKRange feedToken = feedIterator.FeedToken as FeedTokenEPKRange; List <CompositeContinuationToken> deserializedToken = feedToken.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_WithMaxItemCount() { await this.CreateRandomItems(this.Container, 2, randomPartitionKey : true); ContainerCore 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_EmptyBeginning() { int totalCount = 0; int expectedDocuments = 5; bool createdDocuments = false; ContainerCore itemsCore = this.Container; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator() as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults || (createdDocuments && totalCount == 0)) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { Assert.IsNotNull(feedIterator.FeedToken); 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_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_ReadNextAsync() { string continuation = "TBD"; ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK); responseMessage.Headers.ETag = continuation; responseMessage.Headers[Documents.HttpConstants.HttpHeaders.ItemCount] = "1"; Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>(); cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions()); cosmosClientContext .Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.IsAny <Documents.ResourceType>(), It.IsAny <Documents.OperationType>(), It.IsAny <RequestOptions>(), It.IsAny <ContainerInternal>(), It.IsAny <PartitionKey?>(), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(responseMessage)); ContainerInternal containerCore = Mock.Of <ContainerInternal>(); Mock.Get(containerCore) .Setup(c => c.ClientContext) .Returns(cosmosClientContext.Object); FeedRangeInternal range = Mock.Of <FeedRangeInternal>(); Mock.Get(range) .Setup(f => f.Accept(It.IsAny <FeedRangeVisitor>())); FeedRangeContinuation feedToken = Mock.Of <FeedRangeContinuation>(); Mock.Get(feedToken) .Setup(f => f.Accept(It.IsAny <FeedRangeVisitor>(), It.IsAny <Action <RequestMessage, string> >())); Mock.Get(feedToken) .Setup(f => f.FeedRange) .Returns(range); Mock.Get(feedToken) .Setup(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(Documents.ShouldRetryResult.NoRetry())); Mock.Get(feedToken) .Setup(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>())) .Returns(Documents.ShouldRetryResult.NoRetry()); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(containerCore, feedToken, null); ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync(); Mock.Get(feedToken) .Verify(f => f.ReplaceContinuation(It.Is <string>(ct => ct == continuation)), Times.Once); Mock.Get(feedToken) .Verify(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once); Mock.Get(feedToken) .Verify(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>()), Times.Once); }
public async Task ChangeFeedIteratorCore_DoesNotUpdateContinuation_OnError() { string continuation = "TBD"; ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.Gone); responseMessage.Headers.ETag = continuation; Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>(); cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions()); cosmosClientContext .Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <Uri>(), It.IsAny <Documents.ResourceType>(), It.IsAny <Documents.OperationType>(), It.IsAny <RequestOptions>(), It.IsAny <ContainerInternal>(), It.IsAny <PartitionKey?>(), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(responseMessage)); ContainerInternal containerCore = Mock.Of <ContainerInternal>(); Mock.Get(containerCore) .Setup(c => c.ClientContext) .Returns(cosmosClientContext.Object); FeedRangeInternal range = Mock.Of <FeedRangeInternal>(); Mock.Get(range) .Setup(f => f.Accept(It.IsAny <FeedRangeRequestMessagePopulatorVisitor>())); FeedRangeContinuation feedToken = Mock.Of <FeedRangeContinuation>(); Mock.Get(feedToken) .Setup(f => f.FeedRange) .Returns(range); Mock.Get(feedToken) .Setup(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(Documents.ShouldRetryResult.NoRetry())); Mock.Get(feedToken) .Setup(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>())) .Returns(Documents.ShouldRetryResult.NoRetry()); ChangeFeedIteratorCore changeFeedIteratorCore = CreateWithCustomFeedToken(containerCore, feedToken); ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync(); Assert.IsFalse(changeFeedIteratorCore.HasMoreResults); Mock.Get(feedToken) .Verify(f => f.ReplaceContinuation(It.Is <string>(ct => ct == continuation)), Times.Never); Mock.Get(feedToken) .Verify(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once); Mock.Get(feedToken) .Verify(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>()), Times.Once); }
public async Task ChangeFeedIteratorCore_HandlesSplitsThroughPipeline() { int executionCount = 0; CosmosClientContext cosmosClientContext = GetMockedClientContext((RequestMessage requestMessage, CancellationToken cancellationToken) => { // Force OnBeforeRequestActions call requestMessage.ToDocumentServiceRequest(); if (executionCount++ == 0) { return(TestHandler.ReturnStatusCode(HttpStatusCode.Gone, Documents.SubStatusCodes.PartitionKeyRangeGone)); } return(TestHandler.ReturnStatusCode(HttpStatusCode.OK)); }); ContainerInternal containerCore = Mock.Of <ContainerInternal>(); Mock.Get(containerCore) .Setup(c => c.ClientContext) .Returns(cosmosClientContext); Mock.Get(containerCore) .Setup(c => c.LinkUri) .Returns(new Uri("https://dummy.documents.azure.com:443/dbs")); FeedRangeInternal range = Mock.Of <FeedRangeInternal>(); Mock.Get(range) .Setup(f => f.Accept(It.IsAny <FeedRangeVisitor>())); FeedRangeContinuation feedToken = Mock.Of <FeedRangeContinuation>(); Mock.Get(feedToken) .Setup(f => f.Accept(It.IsAny <FeedRangeVisitor>(), It.IsAny <Action <RequestMessage, string> >())); Mock.Get(feedToken) .Setup(f => f.FeedRange) .Returns(range); Mock.Get(feedToken) .Setup(f => f.Accept(It.IsAny <FeedRangeVisitor>(), It.IsAny <Action <RequestMessage, string> >())); Mock.Get(feedToken) .Setup(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(Documents.ShouldRetryResult.NoRetry())); Mock.Get(feedToken) .Setup(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>())) .Returns(Documents.ShouldRetryResult.NoRetry()); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(containerCore, feedToken, null); ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync(); Assert.AreEqual(1, executionCount, "PartitionKeyRangeGoneRetryHandler handled the Split"); Assert.AreEqual(HttpStatusCode.Gone, response.StatusCode); Mock.Get(feedToken) .Verify(f => f.ReplaceContinuation(It.IsAny <string>()), Times.Never); Mock.Get(feedToken) .Verify(f => f.HandleSplitAsync(It.Is <ContainerInternal>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Once); Mock.Get(feedToken) .Verify(f => f.HandleChangeFeedNotModified(It.IsAny <ResponseMessage>()), Times.Once); }
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 ChangeFeedIteratorCore_ReadAll() { int totalCount = 0; int firstRunTotal = 25; int batchSize = 25; await this.CreateRandomItems(this.Container, batchSize, randomPartitionKey : true); ContainerCore itemsCore = this.Container; ChangeFeedIteratorCore feedIterator = itemsCore.GetChangeFeedStreamIterator(changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { Assert.IsNotNull(feedIterator.FeedToken); if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; totalCount += response.Count; } } } 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.Container, batchSize, randomPartitionKey : true); ChangeFeedIteratorCore setIteratorNew = itemsCore.GetChangeFeedStreamIterator(feedToken: feedIterator.FeedToken, changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (setIteratorNew.HasMoreResults) { using (ResponseMessage responseMessage = await setIteratorNew.ReadNextAsync(this.cancellationToken)) { Assert.IsNotNull(setIteratorNew.FeedToken); 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_Retries() { string continuation = "TBD"; ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK); responseMessage.Headers.ETag = continuation; Mock <CosmosClientContext> cosmosClientContext = new Mock <CosmosClientContext>(); cosmosClientContext.Setup(c => c.ClientOptions).Returns(new CosmosClientOptions()); cosmosClientContext .Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <Uri>(), It.IsAny <Documents.ResourceType>(), It.IsAny <Documents.OperationType>(), It.IsAny <RequestOptions>(), It.IsAny <ContainerCore>(), It.IsAny <PartitionKey?>(), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(responseMessage)); ContainerCore containerCore = Mock.Of <ContainerCore>(); FeedTokenInternal feedToken = Mock.Of <FeedTokenInternal>(); Mock.Get(feedToken) .Setup(f => f.EnrichRequest(It.IsAny <RequestMessage>())); Mock.Get(feedToken) .SetupSequence(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(true)) .Returns(Task.FromResult(false)); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore(cosmosClientContext.Object, containerCore, feedToken, null); ResponseMessage response = await changeFeedIteratorCore.ReadNextAsync(); Mock.Get(feedToken) .Verify(f => f.UpdateContinuation(It.IsAny <string>()), Times.Exactly(2)); Mock.Get(feedToken) .Verify(f => f.ShouldRetryAsync(It.Is <ContainerCore>(c => c == containerCore), It.IsAny <ResponseMessage>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); Mock.Get(cosmosClientContext.Object) .Verify(c => c.ProcessResourceOperationStreamAsync( It.IsAny <Uri>(), It.IsAny <Documents.ResourceType>(), It.IsAny <Documents.OperationType>(), It.IsAny <RequestOptions>(), It.IsAny <ContainerCore>(), It.IsAny <PartitionKey?>(), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); }
public async Task ChangeFeedIteratorCore_UpdatesContinuation_On304() { IDocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems : 0); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore( documentContainer, new ChangeFeedRequestOptions(), ChangeFeedStartFrom.Beginning()); ResponseMessage responseMessage = await changeFeedIteratorCore.ReadNextAsync(); Assert.AreEqual(HttpStatusCode.NotModified, responseMessage.StatusCode); string continuationToken = responseMessage.Headers.ContinuationToken; ResponseMessage responseMessage2 = await changeFeedIteratorCore.ReadNextAsync(); Assert.AreEqual(HttpStatusCode.NotModified, responseMessage.StatusCode); string continuationToken2 = responseMessage2.Headers.ContinuationToken; Assert.AreNotEqual(continuationToken, continuationToken2); }
public async Task ChangeFeedBaselineAsync() { ChangeFeedIteratorCore feedIterator = ((ContainerCore)this.container) .GetChangeFeedStreamIterator( ChangeFeedStartFrom.Beginning()) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync()) { } } }
public async Task ChangeFeedIteratorCore_PartitionKeyRangeId_ReadAll() { int totalDocuments = 200; await this.CreateRandomItems(this.LargerContainer, totalDocuments, randomPartitionKey : true); DocumentFeedResponse <Documents.PartitionKeyRange> ranges = await this.LargerContainer.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(this.LargerContainer.LinkUri); List <FeedToken> tokens = new List <FeedToken>(ranges.Count); foreach (Documents.PartitionKeyRange range in ranges) { tokens.Add(new FeedTokenPartitionKeyRange(range.Id)); } ContainerCore itemsCore = this.LargerContainer; List <Task <int> > tasks = tokens.Select(token => Task.Run(async() => { int count = 0; ChangeFeedIteratorCore iteratorForToken = itemsCore.GetChangeFeedStreamIterator(token, changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (iteratorForToken.HasMoreResults) { using (ResponseMessage responseMessage = await iteratorForToken.ReadNextAsync(this.cancellationToken)) { if (responseMessage.Content != null) { 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 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 ChangeFeedBaselineAsync() { ChangeFeedIteratorCore feedIterator = ((ContainerCore)this.container) .GetChangeFeedStreamIterator( changeFeedRequestOptions: new ChangeFeedRequestOptions() { From = ChangeFeedRequestOptions.StartFrom.CreateFromBeginning(), }) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync()) { } } }
public async Task ChangeFeedBaselineAsync() { ChangeFeedIteratorCore feedIterator = ((ContainerCore)this.container) .GetChangeFeedStreamIterator( changeFeedRequestOptions: new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }) as ChangeFeedIteratorCore; while (feedIterator.HasMoreResults) { using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync()) { } } }
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; } } } }
//[Timeout(30000)] 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); ContainerCore itemsCore = this.LargerContainer; FeedToken feedToken = null; int count = 0; while (true) { ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime() }; ChangeFeedIteratorCore feedIterator = feedToken == null?itemsCore.GetChangeFeedStreamIterator(changeFeedRequestOptions : requestOptions) as ChangeFeedIteratorCore : itemsCore.GetChangeFeedStreamIterator(feedToken, changeFeedRequestOptions: requestOptions) as ChangeFeedIteratorCore; using (ResponseMessage responseMessage = await feedIterator.ReadNextAsync(this.cancellationToken)) { feedToken = feedIterator.FeedToken; if (responseMessage.IsSuccessStatusCode) { Collection <ToDoActivity> response = TestCommon.SerializerCore.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(responseMessage.Content).Data; count += response.Count; } } 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_DoesNotUpdateContinuation_OnError() { int numItems = 100; IDocumentContainer documentContainer = await CreateDocumentContainerAsync( numItems, failureConfigs : new FlakyDocumentContainer.FailureConfigs(inject429s: true, injectEmptyPages: true)); ChangeFeedIteratorCore changeFeedIteratorCore = new ChangeFeedIteratorCore( documentContainer, ChangeFeedMode.Incremental, new ChangeFeedRequestOptions(), ChangeFeedStartFrom.Beginning(), this.MockClientContext()); int count = 0; int numIterations = 500; while (numIterations-- > 0) { ResponseMessage responseMessage = await changeFeedIteratorCore.ReadNextAsync(); if (!(responseMessage.IsSuccessStatusCode || responseMessage.StatusCode == HttpStatusCode.NotModified)) { if (responseMessage.Headers.ContinuationToken != null) { Assert.Fail(); } } else { if (responseMessage.StatusCode != HttpStatusCode.NotModified) { count += GetChanges(responseMessage.Content).Count; } } if (count > numItems) { Assert.Fail(); } } Assert.AreEqual(numItems, count); }
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_FromV2SDK() { ContainerResponse largerContainer = await this.database.CreateContainerAsync( new ContainerProperties(id : Guid.NewGuid().ToString(), partitionKeyPath : "/status"), throughput : 20000, cancellationToken : this.cancellationToken); ContainerCore container = (ContainerInlineCore)largerContainer; int expected = 100; int count = 0; await this.CreateRandomItems(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() { StartTime = DateTime.MinValue.ToUniversalTime(), MaxItemCount = 1 }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator(feedRange: feedRange, 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; } // Construct the continuation's range, using PKRangeId + ETag List <dynamic> ct = new List <dynamic>() { new { min = string.Empty, max = string.Empty, token = firstResponse.Headers.ETag } }; // Extract Etag and manually construct the continuation dynamic oldContinuation = new { V = 0, PKRangeId = pkRangeIds.First(), 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() { MaxItemCount = 100 }; ChangeFeedIteratorCore feedIterator = container.GetChangeFeedStreamIterator(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; } } Assert.AreEqual(expected, count); }
public async Task ChangeFeedIteratorCore_FromV2SDK() { int expected = 100; int count = 0; await this.CreateRandomItems(this.LargerContainer, expected, randomPartitionKey : true); IReadOnlyList <FeedRange> feedRanges = await this.LargerContainer.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) { ChangeFeedRequestOptions requestOptions = new ChangeFeedRequestOptions() { StartTime = DateTime.MinValue.ToUniversalTime(), MaxItemCount = 1 }; ChangeFeedIteratorCore feedIterator = this.LargerContainer.GetChangeFeedStreamIterator(feedRange: feedRange, 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; } // Construct the continuation's range, FeedRange.ToString() = [min,max) string range = feedRange.ToString(); int separator = range.IndexOf(','); string min = range.Substring(1, separator - 1); string max = range.Substring(separator + 1, range.IndexOf(')') - separator - 1); dynamic ctRange = new { min = min, max = max }; List <dynamic> ct = new List <dynamic>() { new { min = min, max = max, token = firstResponse.Headers.ETag, range = ctRange } }; // Extract Etag and manually construct the continuation dynamic oldContinuation = new { V = 0, Range = ctRange, 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() { MaxItemCount = 100 }; ChangeFeedIteratorCore feedIterator = this.LargerContainer.GetChangeFeedStreamIterator(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; } } 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)); } ContainerCore 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 : "/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 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) { } }