Ejemplo n.º 1
0
        public void ExtractLsnFromSessionToken_ShouldParseNewSessionTokenWithMultipleRegionalLsn()
        {
            string newTokenWithRegionalLsn = "0:-1#12345#Region1=1#Region2=2";
            string expectedLsn             = "12345";

            Assert.Equal(expectedLsn, RemainingWorkEstimator.ExtractLsnFromSessionToken(newTokenWithRegionalLsn));
        }
Ejemplo n.º 2
0
        public void ExtractLsnFromSessionToken_ShouldParseNewSessionToken()
        {
            string newToken    = "0:-1#12345";
            string expectedLsn = "12345";

            Assert.Equal(expectedLsn, RemainingWorkEstimator.ExtractLsnFromSessionToken(newToken));
        }
Ejemplo n.º 3
0
        private FeedEstimator BuildFeedEstimator()
        {
            if (this.remainingWorkEstimator == null)
            {
                Func <string, string, bool, FeedIterator> feedCreator = (string partitionKeyRangeId, string continuationToken, bool startFromBeginning) =>
                {
                    return(ResultSetIteratorUtils.BuildResultSetIterator(
                               partitionKeyRangeId: partitionKeyRangeId,
                               continuationToken: continuationToken,
                               maxItemCount: 1,
                               cosmosContainer: this.monitoredContainer,
                               startTime: null,
                               startFromBeginning: string.IsNullOrEmpty(continuationToken)));
                };

                this.remainingWorkEstimator = new RemainingWorkEstimatorCore(
                    this.documentServiceLeaseStoreManager.LeaseContainer,
                    feedCreator,
                    this.monitoredContainer.ClientContext.Client.ClientOptions?.GatewayModeMaxConnectionLimit ?? 1);
            }

            ChangeFeedEstimatorDispatcher estimatorDispatcher = new ChangeFeedEstimatorDispatcher(this.initialEstimateDelegate, this.estimatorPeriod);

            return(new FeedEstimatorCore(estimatorDispatcher, this.remainingWorkEstimator));
        }
Ejemplo n.º 4
0
 internal ChangeFeedEstimatorCore(
     Func <long, CancellationToken, Task> initialEstimateDelegate,
     TimeSpan?estimatorPeriod,
     RemainingWorkEstimator remainingWorkEstimator) : this(initialEstimateDelegate, estimatorPeriod)
 {
     this.remainingWorkEstimator = remainingWorkEstimator;
 }
Ejemplo n.º 5
0
        public void ExtractLsnFromSessionToken_ShouldParseOldSessionToken()
        {
            string oldToken    = "0:12345";
            string expectedLsn = "12345";

            Assert.Equal(expectedLsn, RemainingWorkEstimator.ExtractLsnFromSessionToken(oldToken));
        }
Ejemplo n.º 6
0
 internal ChangeFeedEstimatorCore(
     ChangesEstimationHandler initialEstimateDelegate,
     TimeSpan?estimatorPeriod,
     RemainingWorkEstimator remainingWorkEstimator)
     : this(initialEstimateDelegate, estimatorPeriod)
 {
     this.remainingWorkEstimator = remainingWorkEstimator;
 }
Ejemplo n.º 7
0
        public async Task EstimateTotal_ShouldReturnOne_IfNoLeaseDocumentsCreated()
        {
            IReadOnlyList <ILease> leases = new List <ILease>(0);
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>(),
                collectionSelfLink,
                1);
            long pendingWork = await sut.GetEstimatedRemainingWork();

            Assert.Equal(1, pendingWork);
        }
        public RemainingWorkEstimatorTests()
        {
            var document = new Document();

            document.SetPropertyValue("_lsn", "10");
            documents = new List <Document> {
                document
            };

            feedResponse = Mock.Of <IFeedResponse <Document> >();
            Mock.Get(feedResponse)
            .Setup(response => response.SessionToken)
            .Returns("0:15");

            Mock.Get(feedResponse)
            .Setup(response => response.Count)
            .Returns(documents.Count);

            Mock.Get(feedResponse)
            .Setup(response => response.GetEnumerator())
            .Returns(documents.GetEnumerator());

            lease = Mock.Of <ILease>();
            Mock.Get(lease)
            .Setup(l => l.PartitionId)
            .Returns("partitionId");

            leaseManager = Mock.Of <ILeaseManager>();
            Mock.Get(leaseManager)
            .Setup(manager => manager.ListAllLeasesAsync())
            .ReturnsAsync(new List <ILease>()
            {
                lease
            });

            documentQuery = Mock.Of <IChangeFeedDocumentQuery <Document> >();
            Mock.Get(documentQuery)
            .Setup(query => query.HasMoreResults)
            .Returns(false);

            Mock.Get(documentQuery)
            .Setup(query => query.ExecuteNextAsync <Document>(It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => feedResponse)
            .Callback(() => cancellationTokenSource.Cancel());

            docClient = Mock.Of <IChangeFeedDocumentClient>();
            Mock.Get(docClient)
            .Setup(ex => ex.CreateDocumentChangeFeedQuery(collectionSelfLink, It.IsAny <ChangeFeedOptions>()))
            .Returns(documentQuery);

            remainingWorkEstimator = new RemainingWorkEstimator(leaseManager, docClient, collectionSelfLink);
        }
Ejemplo n.º 9
0
        public async Task EstimateTotal_ShouldPropagateExecption_IfUnknownExceptionHappened()
        {
            IReadOnlyList <ILease> leases = new List <ILease>(0);
            var leaseContainer            = new Mock <ILeaseContainer>();

            leaseContainer.Setup(m => m.GetAllLeasesAsync()).ThrowsAsync(new InvalidOperationException());
            var sut = new RemainingWorkEstimator(
                leaseContainer.Object,
                Mock.Of <IChangeFeedDocumentClient>(),
                collectionSelfLink,
                1);
            await Assert.ThrowsAsync <InvalidOperationException>(sut.GetEstimatedRemainingWork);
        }
Ejemplo n.º 10
0
        private FeedEstimator BuildFeedEstimator()
        {
            if (this.remainingWorkEstimator == null)
            {
                this.remainingWorkEstimator = new RemainingWorkEstimatorCore(
                    this.documentServiceLeaseStoreManager.LeaseContainer,
                    this.monitoredContainer,
                    this.monitoredContainer.ClientContext.Client.Configuration?.MaxConnectionLimit ?? 1);
            }

            ChangeFeedEstimatorDispatcher estimatorDispatcher = new ChangeFeedEstimatorDispatcher(this.initialEstimateDelegate, this.estimatorPeriod);

            return(new FeedEstimatorCore(estimatorDispatcher, this.remainingWorkEstimator));
        }
Ejemplo n.º 11
0
        public async Task EstimateTotal_ShouldReturnPendingWork_IfOnePartition()
        {
            IReadOnlyList <ILease> leases = new List <ILease> {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100")
            };
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponse("1", "100", "101", "1:106"),
                collectionSelfLink,
                1);
            long pendingWork = await sut.GetEstimatedRemainingWork();

            Assert.Equal(6, pendingWork);
        }
Ejemplo n.º 12
0
        public async Task EstimatePerPartition_ShouldReturnEmpty_WhenNothingSucceeds()
        {
            IReadOnlyList <ILease> leases = new List <ILease>
            {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100")
            };
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponseFailure("1", "100"),
                collectionSelfLink,
                1);
            var pendingWork = await sut.GetEstimatedRemainingWorkPerPartitionAsync();

            Assert.Empty(pendingWork);
        }
Ejemplo n.º 13
0
 public async Task EstimateTotal_ShouldRethrowException_IfEstimatorPartitionWorkThrowsUnknonwException()
 {
     IReadOnlyList <ILease> leases = new List <ILease>
     {
         Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100"),
         Mock.Of <ILease>(l => l.PartitionId == "2" && l.ContinuationToken == "200")
     };
     var sut = new RemainingWorkEstimator(
         Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
         Mock.Of <IChangeFeedDocumentClient>()
         .SetupQueryResponse("1", "100", "101", "1:103")
         .SetupQueryResponseFailure("2", "200", new InvalidOperationException()),
         collectionSelfLink,
         1);
     await Assert.ThrowsAsync <InvalidOperationException>(sut.GetEstimatedRemainingWork);
 }
Ejemplo n.º 14
0
        public async Task EstimateForOwnedPartition_ShouldReturnPendingWork_IfOnePartition()
        {
            IEnumerable <ILease> leases = new List <ILease> {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100")
            };
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetOwnedLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponse("1", "100", "101", "1:106"),
                collectionSelfLink,
                1);

            var pendingWork = await sut.GetEstimatedRemainingWorkForOwnedPartitionsAsync();

            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "1" && work.RemainingWork == 6);
            Assert.Single(pendingWork);
        }
Ejemplo n.º 15
0
        public async Task EstimatePerPartition_ShouldReturnZero_WhenEmptyResponse()
        {
            IReadOnlyList <ILease> leases = new List <ILease>
            {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100")
            };
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponse("1", "100", null, "1:100"),
                collectionSelfLink,
                1);

            var pendingWork = await sut.GetEstimatedRemainingWorkPerPartitionAsync();

            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "1" && work.RemainingWork == 0);
            Assert.Single(pendingWork);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Builds a new instance of the <see cref="IRemainingWorkEstimator"/> to estimate pending work with the specified configuration.
        /// </summary>
        /// <returns>An instance of <see cref="IRemainingWorkEstimator"/>.</returns>
        public async Task <IRemainingWorkEstimator> BuildEstimatorAsync()
        {
            if (this.feedCollectionLocation == null)
            {
                throw new InvalidOperationException(nameof(this.feedCollectionLocation) + " was not specified");
            }

            if (this.leaseCollectionLocation == null)
            {
                throw new InvalidOperationException(nameof(this.leaseCollectionLocation) + " was not specified");
            }

            await this.InitializeCollectionPropertiesForBuildAsync().ConfigureAwait(false);

            ILeaseManager leaseManager = await this.GetLeaseManagerAsync().ConfigureAwait(false);

            IRemainingWorkEstimator remainingWorkEstimator = new RemainingWorkEstimator(leaseManager, this.feedDocumentClient, this.feedCollectionLocation.GetCollectionSelfLink());

            return(remainingWorkEstimator);
        }
Ejemplo n.º 17
0
        public async Task EstimatePerPartition_ShouldRunInParallel_IfDegreeOfParallelismIsTwo()
        {
            IReadOnlyList <ILease> leases = new List <ILease>
            {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100"),
                Mock.Of <ILease>(l => l.PartitionId == "2" && l.ContinuationToken == "200")
            };

            TaskCompletionSource <bool> cts1   = new TaskCompletionSource <bool>();
            TaskCompletionSource <bool> cts2   = new TaskCompletionSource <bool>();
            TaskCompletionSource <bool> ctsAll = new TaskCompletionSource <bool>();
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponse("1", "100", "101", "1:106", async r =>
            {
                cts1.SetResult(true);
                await ctsAll.Task;
                return(r);
            })
                .SetupQueryResponse("2", "200", "201", "2:-1#201", async r =>
            {
                cts2.SetResult(true);
                await ctsAll.Task;
                return(r);
            }),
                collectionSelfLink,
                2);

            var workPerPartitionTask = sut.GetEstimatedRemainingWorkPerPartitionAsync();

            await Task.WhenAll(cts1.Task, cts2.Task);

            ctsAll.SetResult(true);

            var pendingWork = await workPerPartitionTask;

            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "1" && work.RemainingWork == 6);
            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "2" && work.RemainingWork == 1);
            Assert.Equal(2, pendingWork.Count);
        }
Ejemplo n.º 18
0
        public async Task EstimatePerPartition_ShouldReturnPendingWork_IfMultiplePartitions()
        {
            IReadOnlyList <ILease> leases = new List <ILease>
            {
                Mock.Of <ILease>(l => l.PartitionId == "1" && l.ContinuationToken == "100"),
                Mock.Of <ILease>(l => l.PartitionId == "2" && l.ContinuationToken == "200")
            };
            var sut = new RemainingWorkEstimator(
                Mock.Of <ILeaseContainer>(m => m.GetAllLeasesAsync() == Task.FromResult(leases)),
                Mock.Of <IChangeFeedDocumentClient>()
                .SetupQueryResponse("1", "100", "101", "1:106")
                .SetupQueryResponse("2", "200", "201", "2:201"),
                collectionSelfLink,
                1);

            var pendingWork = await sut.GetEstimatedRemainingWorkPerPartitionAsync();

            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "1" && work.RemainingWork == 6);
            Assert.Contains(pendingWork, work => work.PartitionKeyRangeId == "2" && work.RemainingWork == 1);
            Assert.Equal(2, pendingWork.Count);
        }
        /// <summary>
        /// Builds a new instance of the <see cref="IRemainingWorkEstimator"/> to estimate pending work with the specified configuration.
        /// </summary>
        /// <returns>An instance of <see cref="IRemainingWorkEstimator"/>.</returns>
        public async Task <IRemainingWorkEstimator> BuildEstimatorAsync()
        {
            if (this.feedCollectionLocation == null)
            {
                throw new InvalidOperationException(nameof(this.feedCollectionLocation) + " was not specified");
            }

            if (this.leaseCollectionLocation == null && this.LeaseStoreManager == null)
            {
                throw new InvalidOperationException($"Either {nameof(this.leaseCollectionLocation)} or {nameof(this.LeaseStoreManager)} must be specified");
            }

            await this.InitializeCollectionPropertiesForBuildAsync().ConfigureAwait(false);

            var leaseStoreManager = await this.GetLeaseStoreManagerAsync(this.leaseCollectionLocation, true).ConfigureAwait(false);

            IRemainingWorkEstimator remainingWorkEstimator = new RemainingWorkEstimator(
                leaseStoreManager,
                this.feedDocumentClient,
                this.feedCollectionLocation.GetCollectionSelfLink(),
                this.feedCollectionLocation.ConnectionPolicy.MaxConnectionLimit);

            return(remainingWorkEstimator);
        }
 public FeedEstimatorCore(ChangeFeedEstimatorDispatcher dispatcher, RemainingWorkEstimator remainingWorkEstimator)
 {
     this.dispatcher             = dispatcher;
     this.remainingWorkEstimator = remainingWorkEstimator;
     this.monitoringDelay        = dispatcher.DispatchPeriod ?? FeedEstimatorCore.defaultMonitoringDelay;
 }