public async Task NextReadHasUpdatedContinuation() { int itemCount = 5; string pkRangeId = "0"; string etag = Guid.NewGuid().ToString(); DateTime startTime = DateTime.UtcNow; DocumentServiceLeaseCore documentServiceLeaseCore = new DocumentServiceLeaseCore() { LeaseToken = pkRangeId }; ResponseMessage firstResponse = new ResponseMessage(System.Net.HttpStatusCode.OK); firstResponse.Headers.ETag = etag; ResponseMessage secondResponse = new ResponseMessage(System.Net.HttpStatusCode.OK); int responseCount = 0; Func <Action <RequestMessage>, bool> validateEnricher = (Action <RequestMessage> enricher) => { RequestMessage requestMessage = new RequestMessage(); enricher(requestMessage); return(responseCount++ == 0 || requestMessage.Headers.IfNoneMatch == etag); }; Mock <ContainerInternal> containerMock = new Mock <ContainerInternal>(); Mock <CosmosClientContext> mockContext = new Mock <CosmosClientContext>(); mockContext.SetupSequence(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.Is <Documents.ResourceType>(rt => rt == Documents.ResourceType.Document), It.Is <Documents.OperationType>(rt => rt == Documents.OperationType.ReadFeed), It.Is <ChangeFeedRequestOptions>(cfo => cfo.PageSizeHint == itemCount), It.Is <ContainerInternal>(o => o == containerMock.Object), It.IsAny <FeedRange>(), It.IsAny <Stream>(), It.Is <Action <RequestMessage> >(enricher => validateEnricher(enricher)), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <ITrace>(), It.IsAny <CancellationToken>() ) ) .ReturnsAsync(firstResponse) .ReturnsAsync(secondResponse); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, startTime: startTime, startFromBeginning: false); await iterator.ReadNextAsync(); await iterator.ReadNextAsync(); Assert.AreEqual(2, responseCount); }
public override FeedProcessor Create(DocumentServiceLease lease, ChangeFeedObserver <T> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (lease == null) { throw new ArgumentNullException(nameof(lease)); } ProcessorOptions options = new ProcessorOptions { StartContinuation = !string.IsNullOrEmpty(lease.ContinuationToken) ? lease.ContinuationToken : this.changeFeedProcessorOptions.StartContinuation, LeaseToken = lease.CurrentLeaseToken, FeedPollDelay = this.changeFeedProcessorOptions.FeedPollDelay, MaxItemCount = this.changeFeedProcessorOptions.MaxItemCount, StartFromBeginning = this.changeFeedProcessorOptions.StartFromBeginning, StartTime = this.changeFeedProcessorOptions.StartTime, SessionToken = this.changeFeedProcessorOptions.SessionToken, }; PartitionCheckpointerCore checkpointer = new PartitionCheckpointerCore(this.leaseCheckpointer, lease); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: lease, continuationToken: options.StartContinuation, maxItemCount: options.MaxItemCount, container: this.container, startTime: options.StartTime, startFromBeginning: options.StartFromBeginning); return(new FeedProcessorCore <T>(observer, iterator, options, checkpointer, this.serializerCore)); }
public async Task ShouldSetFeedRangePartitionKeyRange() { int itemCount = 5; string pkRangeId = "0"; string etag = Guid.NewGuid().ToString(); DateTime startTime = DateTime.UtcNow; DocumentServiceLeaseCore documentServiceLeaseCore = new DocumentServiceLeaseCore() { LeaseToken = pkRangeId }; Mock <ContainerInternal> containerMock = new Mock <ContainerInternal>(); Mock <CosmosClientContext> mockContext = new Mock <CosmosClientContext>(); mockContext.Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.Is <Documents.ResourceType>(rt => rt == Documents.ResourceType.Document), It.Is <Documents.OperationType>(rt => rt == Documents.OperationType.ReadFeed), It.Is <ChangeFeedRequestOptions>(cfo => cfo.PageSizeHint == itemCount), It.Is <ContainerInternal>(o => o == containerMock.Object), It.Is <FeedRange>(fr => fr is FeedRangePartitionKeyRange), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <ITrace>(), It.IsAny <CancellationToken>() ) ).ReturnsAsync(new ResponseMessage(System.Net.HttpStatusCode.OK)); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, startTime: startTime, startFromBeginning: false); ResponseMessage response = await iterator.ReadNextAsync(); Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); mockContext.Verify(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.Is <Documents.ResourceType>(rt => rt == Documents.ResourceType.Document), It.Is <Documents.OperationType>(rt => rt == Documents.OperationType.ReadFeed), It.Is <ChangeFeedRequestOptions>(cfo => cfo.PageSizeHint == itemCount), It.Is <ContainerInternal>(o => o == containerMock.Object), It.Is <FeedRange>(fr => fr is FeedRangePartitionKeyRange), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.IsAny <CosmosDiagnosticsContext>(), It.IsAny <ITrace>(), It.IsAny <CancellationToken>() ), Times.Once); }
public async Task ShouldUseFeedRangeEpk() { int itemCount = 5; string pkRangeId = "0"; DateTime startTime = DateTime.UtcNow; Documents.Routing.Range <string> range = new Documents.Routing.Range <string>("AA", "BB", true, false); FeedRangeEpk feedRange = new FeedRangeEpk(range); DocumentServiceLeaseCoreEpk documentServiceLeaseCore = new DocumentServiceLeaseCoreEpk() { LeaseToken = pkRangeId, FeedRange = feedRange }; Mock <ContainerInternal> containerMock = new Mock <ContainerInternal>(); Mock <CosmosClientContext> mockContext = new Mock <CosmosClientContext>(); mockContext.Setup(x => x.OperationHelperAsync <ResponseMessage>( It.Is <string>(str => str.Contains("Change Feed Processor")), It.IsAny <RequestOptions>(), It.IsAny <Func <ITrace, Task <ResponseMessage> > >(), It.Is <TraceComponent>(tc => tc == TraceComponent.ChangeFeed), It.IsAny <TraceLevel>())) .Returns <string, RequestOptions, Func <ITrace, Task <ResponseMessage> >, TraceComponent, TraceLevel>( (operationName, requestOptions, func, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { return(func(trace)); } }); mockContext.Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.Is <Documents.ResourceType>(rt => rt == Documents.ResourceType.Document), It.Is <Documents.OperationType>(rt => rt == Documents.OperationType.ReadFeed), It.Is <ChangeFeedRequestOptions>(cfo => cfo.PageSizeHint == itemCount), It.Is <ContainerInternal>(o => o == containerMock.Object), It.Is <FeedRange>(fr => fr is FeedRangeEpk), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.Is <ITrace>(t => !(t is NoOpTrace)), It.IsAny <CancellationToken>() ) ).ReturnsAsync(new ResponseMessage(System.Net.HttpStatusCode.OK)); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); MockDocumentClient mockDocumentClient = new MockDocumentClient(); mockContext.Setup(c => c.DocumentClient).Returns(mockDocumentClient); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, startTime: startTime, startFromBeginning: false); ResponseMessage response = await iterator.ReadNextAsync(); Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); mockContext.Verify(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.Is <Documents.ResourceType>(rt => rt == Documents.ResourceType.Document), It.Is <Documents.OperationType>(rt => rt == Documents.OperationType.ReadFeed), It.Is <ChangeFeedRequestOptions>(cfo => cfo.PageSizeHint == itemCount), It.Is <ContainerInternal>(o => o == containerMock.Object), It.Is <FeedRange>(fr => fr is FeedRangeEpk), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.Is <ITrace>(t => !(t is NoOpTrace)), It.IsAny <CancellationToken>() ), Times.Once); }
public async Task EtagPassesContinuation() { int itemCount = 5; string pkRangeId = "0"; string etag = Guid.NewGuid().ToString(); DateTime startTime = DateTime.UtcNow; DocumentServiceLeaseCore documentServiceLeaseCore = new DocumentServiceLeaseCore() { LeaseToken = pkRangeId }; ResponseMessage responseMessage = new ResponseMessage(System.Net.HttpStatusCode.OK); responseMessage.Headers.ETag = etag; Mock <ContainerInternal> containerMock = new Mock <ContainerInternal>(); Mock <CosmosClientContext> mockContext = new Mock <CosmosClientContext>(); mockContext.Setup(x => x.OperationHelperAsync <ResponseMessage>( It.Is <string>(str => str.Contains("Change Feed Processor")), It.IsAny <RequestOptions>(), It.IsAny <Func <ITrace, Task <ResponseMessage> > >(), It.Is <TraceComponent>(tc => tc == TraceComponent.ChangeFeed), It.IsAny <TraceLevel>())) .Returns <string, RequestOptions, Func <ITrace, Task <ResponseMessage> >, TraceComponent, TraceLevel>( (operationName, requestOptions, func, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { return(func(trace)); } }); mockContext.Setup(c => c.ProcessResourceOperationStreamAsync( It.IsAny <string>(), It.IsAny <Documents.ResourceType>(), It.IsAny <Documents.OperationType>(), It.IsAny <ChangeFeedRequestOptions>(), It.IsAny <ContainerInternal>(), It.IsAny <FeedRange>(), It.IsAny <Stream>(), It.IsAny <Action <RequestMessage> >(), It.Is <ITrace>(t => !(t is NoOpTrace)), It.IsAny <CancellationToken>() ) ).ReturnsAsync(responseMessage); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, startTime: startTime, startFromBeginning: false); ResponseMessage response = await iterator.ReadNextAsync(); Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); Assert.AreEqual(etag, response.Headers.ContinuationToken); }