internal PartitionManager BuildPartitionManager()
        {
            CheckpointerObserverFactory <T> factory      = new CheckpointerObserverFactory <T>(this.observerFactory, this.changeFeedProcessorOptions.CheckpointFrequency);
            PartitionSynchronizerCore       synchronizer = new PartitionSynchronizerCore(
                this.monitoredContainer,
                this.documentServiceLeaseStoreManager.LeaseContainer,
                this.documentServiceLeaseStoreManager.LeaseManager,
                PartitionSynchronizerCore.DefaultDegreeOfParallelism,
                this.changeFeedProcessorOptions.QueryFeedMaxBatchSize);
            BootstrapperCore bootstrapper = new BootstrapperCore(synchronizer, this.documentServiceLeaseStoreManager.LeaseStore, BootstrapperCore.DefaultLockTime, BootstrapperCore.DefaultSleepTime);
            PartitionSupervisorFactoryCore <T> partitionSuperviserFactory = new PartitionSupervisorFactoryCore <T>(
                factory,
                this.documentServiceLeaseStoreManager.LeaseManager,
                new FeedProcessorFactoryCore <T>(this.monitoredContainer, this.changeFeedProcessorOptions, this.documentServiceLeaseStoreManager.LeaseCheckpointer, this.monitoredContainer.ClientContext.SerializerCore),
                this.changeFeedLeaseOptions);

            EqualPartitionsBalancingStrategy loadBalancingStrategy = new EqualPartitionsBalancingStrategy(
                this.instanceName,
                EqualPartitionsBalancingStrategy.DefaultMinLeaseCount,
                EqualPartitionsBalancingStrategy.DefaultMaxLeaseCount,
                this.changeFeedLeaseOptions.LeaseExpirationInterval);

            PartitionController partitionController = new PartitionControllerCore(this.documentServiceLeaseStoreManager.LeaseContainer, this.documentServiceLeaseStoreManager.LeaseManager, partitionSuperviserFactory, synchronizer);

            partitionController = new HealthMonitoringPartitionControllerDecorator(partitionController, new TraceHealthMonitor());
            PartitionLoadBalancerCore partitionLoadBalancer = new PartitionLoadBalancerCore(
                partitionController,
                this.documentServiceLeaseStoreManager.LeaseContainer,
                loadBalancingStrategy,
                this.changeFeedLeaseOptions.LeaseAcquireInterval);

            return(new PartitionManagerCore(bootstrapper, partitionController, partitionLoadBalancer));
        }
        public async Task HandlePartitionGoneAsync_EpkBasedLease_Merge()
        {
            string continuation = Guid.NewGuid().ToString();

            Documents.Routing.Range <string> range = new Documents.Routing.Range <string>("AA", "EE", true, false);
            DocumentServiceLeaseCoreEpk      lease = new DocumentServiceLeaseCoreEpk()
            {
                LeaseToken        = "AA-BB",
                ContinuationToken = continuation,
                Owner             = Guid.NewGuid().ToString(),
                FeedRange         = new FeedRangeEpk(range)
            };

            Mock <Routing.PartitionKeyRangeCache> pkRangeCache = new Mock <Routing.PartitionKeyRangeCache>(
                Mock.Of <Documents.IAuthorizationTokenProvider>(),
                Mock.Of <Documents.IStoreModel>(),
                Mock.Of <Common.CollectionCache>());

            List <Documents.PartitionKeyRange> resultingRanges = new List <Documents.PartitionKeyRange>()
            {
                new Documents.PartitionKeyRange()
                {
                    Id = "1", MinInclusive = "", MaxExclusive = "FF"
                },
            };

            pkRangeCache.Setup(p => p.TryGetOverlappingRangesAsync(
                                   It.IsAny <string>(),
                                   It.Is <Documents.Routing.Range <string> >(r => r.Min == range.Min && r.Max == range.Max),
                                   It.IsAny <ITrace>(),
                                   true))
            .ReturnsAsync(resultingRanges);

            Mock <DocumentServiceLeaseManager> leaseManager = new Mock <DocumentServiceLeaseManager>();

            PartitionSynchronizerCore partitionSynchronizerCore = new PartitionSynchronizerCore(
                Mock.Of <ContainerInternal>(),
                Mock.Of <DocumentServiceLeaseContainer>(),
                leaseManager.Object,
                1,
                pkRangeCache.Object,
                Guid.NewGuid().ToString());

            (IEnumerable <DocumentServiceLease> addedLeases, bool shouldDelete) = await partitionSynchronizerCore.HandlePartitionGoneAsync(lease);

            Assert.IsFalse(shouldDelete);

            Assert.AreEqual(lease, addedLeases.First());

            leaseManager.Verify(l => l.CreateLeaseIfNotExistAsync(
                                    It.IsAny <Documents.PartitionKeyRange>(),
                                    It.IsAny <string>()), Times.Never);

            leaseManager.Verify(l => l.CreateLeaseIfNotExistAsync(
                                    It.IsAny <FeedRangeEpk>(),
                                    It.IsAny <string>()), Times.Never);
        }
        public async Task HandlePartitionGoneAsync_PKRangeBasedLease_Merge()
        {
            string continuation = Guid.NewGuid().ToString();

            Documents.Routing.Range <string> range = new Documents.Routing.Range <string>("", "BB", true, false);
            DocumentServiceLeaseCore         lease = new DocumentServiceLeaseCore()
            {
                LeaseToken        = "0",
                ContinuationToken = continuation,
                Owner             = Guid.NewGuid().ToString(),
                FeedRange         = new FeedRangeEpk(range)
            };

            Mock <Routing.PartitionKeyRangeCache> pkRangeCache = new Mock <Routing.PartitionKeyRangeCache>(
                Mock.Of <Documents.IAuthorizationTokenProvider>(),
                Mock.Of <Documents.IStoreModel>(),
                Mock.Of <Common.CollectionCache>());

            List <Documents.PartitionKeyRange> resultingRanges = new List <Documents.PartitionKeyRange>()
            {
                new Documents.PartitionKeyRange()
                {
                    Id = "2", MinInclusive = "", MaxExclusive = "FF"
                }
            };

            pkRangeCache.Setup(p => p.TryGetOverlappingRangesAsync(
                                   It.IsAny <string>(),
                                   It.Is <Documents.Routing.Range <string> >(r => r.Min == range.Min && r.Max == range.Max),
                                   It.IsAny <ITrace>(),
                                   It.Is <bool>(b => b == true)))
            .ReturnsAsync(resultingRanges);

            Mock <DocumentServiceLeaseManager> leaseManager = new Mock <DocumentServiceLeaseManager>();

            PartitionSynchronizerCore partitionSynchronizerCore = new PartitionSynchronizerCore(
                Mock.Of <ContainerInternal>(),
                Mock.Of <DocumentServiceLeaseContainer>(),
                leaseManager.Object,
                1,
                pkRangeCache.Object,
                Guid.NewGuid().ToString());

            await partitionSynchronizerCore.HandlePartitionGoneAsync(lease);

            leaseManager.Verify(l => l.CreateLeaseIfNotExistAsync(
                                    It.IsAny <Documents.PartitionKeyRange>(),
                                    It.IsAny <string>()), Times.Never);

            leaseManager.Verify(l => l.CreateLeaseIfNotExistAsync(
                                    It.IsAny <FeedRangeEpk>(),
                                    It.IsAny <string>()), Times.Once);

            leaseManager.Verify(l => l.CreateLeaseIfNotExistAsync(
                                    It.Is <FeedRangeEpk>(epKRange => epKRange.Range.Min == range.Min && epKRange.Range.Max == range.Max),
                                    It.Is <string>(c => c == continuation)), Times.Once);
        }
        public async Task CreateMissingLeases_SomePKRangeLeases()
        {
            Mock <Routing.PartitionKeyRangeCache> pkRangeCache = new Mock <Routing.PartitionKeyRangeCache>(
                Mock.Of <Documents.IAuthorizationTokenProvider>(),
                Mock.Of <Documents.IStoreModel>(),
                Mock.Of <Common.CollectionCache>());

            List <Documents.PartitionKeyRange> resultingRanges = new List <Documents.PartitionKeyRange>()
            {
                new Documents.PartitionKeyRange()
                {
                    Id = "1", MinInclusive = "", MaxExclusive = "BB"
                },
                new Documents.PartitionKeyRange()
                {
                    Id = "2", MinInclusive = "BB", MaxExclusive = "FF"
                },
            };

            pkRangeCache.Setup(p => p.TryGetOverlappingRangesAsync(
                                   It.IsAny <string>(),
                                   It.IsAny <Documents.Routing.Range <string> >(),
                                   It.IsAny <ITrace>(),
                                   false))
            .ReturnsAsync(resultingRanges);

            Mock <DocumentServiceLeaseManager> leaseManager = new Mock <DocumentServiceLeaseManager>();

            // Existing for only one partition
            List <DocumentServiceLease> existingLeases = new List <DocumentServiceLease>()
            {
                new DocumentServiceLeaseCore()
                {
                    LeaseToken = resultingRanges[0].Id,
                    Owner      = Guid.NewGuid().ToString()
                }
            };

            Mock <DocumentServiceLeaseContainer> leaseContainer = new Mock <DocumentServiceLeaseContainer>();

            leaseContainer.Setup(c => c.GetAllLeasesAsync())
            .ReturnsAsync(existingLeases);

            PartitionSynchronizerCore partitionSynchronizerCore = new PartitionSynchronizerCore(
                Mock.Of <ContainerInternal>(),
                leaseContainer.Object,
                leaseManager.Object,
                1,
                pkRangeCache.Object,
                Guid.NewGuid().ToString());

            await partitionSynchronizerCore.CreateMissingLeasesAsync();

            leaseManager.Verify(m => m.CreateLeaseIfNotExistAsync(It.Is <PartitionKeyRange>(pkRange => pkRange.Id == resultingRanges[1].Id), It.IsAny <string>()), Times.Once);
            leaseManager.Verify(m => m.CreateLeaseIfNotExistAsync(It.IsAny <PartitionKeyRange>(), It.IsAny <string>()), Times.Exactly(1));
        }