/// <summary>
        /// Initializes the partition resolver to be used with Item repository.
        /// </summary>
        /// <param name="resolverService"></param>
        public async void getResolver(int resolverService)
        {
            switch (resolverService)
            {
            case Hash:
                HashPartitionResolver hashResolver = await PartitionInitializers.InitializeHashResolver("tenantId", Client, Database, collections);

                break;

            case ManagedHash:
                ManagedHashPartitionResolver managedHashResolver = PartitionInitializers.InitializeManagedHashResolver(i => ((Item)i).tenantId, Client, Database, 3, null);
                break;

            case Spillover:
                SpilloverPartitionResolver spilloverResolver = new SpilloverPartitionResolver(Client, Database);
                Client.PartitionResolvers[Database.SelfLink] = spilloverResolver;
                break;

            case Range:
                RangePartitionResolver <string> rangeResolver = await PartitionInitializers.InitializeRangeResolver("tenantId", Client, Database, collections);

                break;

            case Lookup:
                LookupPartitionResolver <string> lookupResolver = await PartitionInitializers.InitializeLookupPartitionResolver("tenantId", Client, Database, collections);

                break;

            default:
                goto case Hash;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Removes a partition (collection) from the consistent hash ring.
        /// </summary>
        /// <returns>The Task object for the asynchronous execution.</returns>
        public async Task <int> RemovePartition()
        {
            ManagedHashPartitionResolver currentResolver = (ManagedHashPartitionResolver)this.Client.PartitionResolvers[this.Database.SelfLink];
            int numberOfMovedDocuments = await this.RepartitionData(currentResolver.PartitionCount - 1);

            await this.Client.DeleteDocumentCollectionAsync(currentResolver.CollectionLinks.Last());

            return(numberOfMovedDocuments);
        }
Esempio n. 3
0
        /// <summary>
        /// Initialize a "managed" HashPartitionResolver that also takes care of creating collections, and cloning collection properties like
        /// stored procedures, offer type and indexing policy.
        /// </summary>
        /// <param name="database">The database to run the samples on.</param>
        /// <returns>The created HashPartitionResolver.</returns>
        private ManagedHashPartitionResolver InitializeManagedHashResolver(Database database)
        {
            var hashResolver = new ManagedHashPartitionResolver(u => ((UserProfile)u).UserId, this.client, database, 3, null, new DocumentCollectionSpec {
                OfferType = "S2"
            });

            this.client.PartitionResolvers[database.SelfLink] = hashResolver;
            return(hashResolver);
        }
        public async Task <IHttpActionResult> ManagedHashPartitionResolver()
        {
            string[] collections = AppSettingsConfig.MainCollection.Split(',');
            var      database    = await DocumentClientHelper.GetNewDatabaseAsync(_client, AppSettingsConfig.Db);

            ManagedHashPartitionResolver managedHashResolver = PartitionInitializers.InitializeManagedHashResolver(u => ((UserProfile)u).UserId, _client, database, 3, null);

            return(Ok());
        }
Esempio n. 5
0
        /// <summary>
        /// Internal method to rebalance data across a different number of partitions.
        /// </summary>
        /// <param name="newPartitionCount">The target number of partitions.</param>
        /// <returns>The Task object for the asynchronous execution.</returns>
        private async Task <int> RepartitionData(int newPartitionCount)
        {
            // No-op, just delete the last collection.
            if (newPartitionCount == 0)
            {
                return(0);
            }

            ManagedHashPartitionResolver currentResolver = (ManagedHashPartitionResolver)this.Client.PartitionResolvers[this.Database.SelfLink];

            var nextPartitionResolver = new ManagedHashPartitionResolver(
                currentResolver.PartitionKeyExtractor,
                this.Client,
                this.Database,
                newPartitionCount);

            TransitionHashPartitionResolver transitionaryResolver = new TransitionHashPartitionResolver(
                currentResolver,
                nextPartitionResolver,
                this.ReadMode);

            this.Client.PartitionResolvers[this.Database.SelfLink] = transitionaryResolver;

            // Move data between partitions. Here it's one by one, but you can change this to implement inserts
            // in bulk using stored procedures (bulkImport and bulkDelete), or run them in parallel. Another
            // improvement to this would be push down the check for partitioning function down to the individual
            // collections as a LINQ/SQL query.
            int numberOfMovedDocuments = 0;

            foreach (string collectionLink in currentResolver.CollectionLinks)
            {
                ResourceFeedReader <Document> feedReader = this.Client.CreateDocumentFeedReader(collectionLink);

                while (feedReader.HasMoreResults)
                {
                    foreach (Document document in await feedReader.ExecuteNextAsync())
                    {
                        object partitionKey      = nextPartitionResolver.GetPartitionKey(document);
                        string newCollectionLink = nextPartitionResolver.ResolveForCreate(partitionKey);

                        if (newCollectionLink != collectionLink)
                        {
                            numberOfMovedDocuments++;
                            await this.Client.DeleteDocumentAsync(document.SelfLink);

                            await this.Client.CreateDocumentAsync(newCollectionLink, document);
                        }
                    }
                }
            }

            this.Client.PartitionResolvers[this.Database.SelfLink] = nextPartitionResolver;
            return(numberOfMovedDocuments);
        }
Esempio n. 6
0
        /// <summary>
        /// Initializes the partition resolver to be used with Item repository.
        /// </summary>
        /// <param name="resolverService"></param>
        public async void getResolver(int resolverService)
        {
            switch (resolverService)
            {
            case Hash:
                HashPartitionResolver hashResolver = await PartitionInitializers.InitializeHashResolver("docType", Client, Database, collections);

                break;

            case ManagedHash:
                ManagedHashPartitionResolver managedHashResolver = PartitionInitializers.InitializeManagedHashResolver(i => ((ItemBase)i).docType, Client, Database, 3, null);
                break;

            default:
                goto case Hash;
            }
        }
 /// <summary>
 /// Initialize a "managed" HashPartitionResolver that also takes care of creating collections, and cloning collection properties like
 /// stored procedures, offer type and indexing policy.
 /// </summary>
 /// <param name="partitionKeyExtractor">The partition key extractor function. (Ex: "u => ((UserProfile)u).UserId")</param>
 /// <param name="client">The DocumentDB client instance to use.</param>
 /// <param name="database">The database to run the samples on.</param>
 /// <param name="numCollections">The number of collections to be used.</param>
 /// <param name="collectionSpec">The DocumentCollectionSpec to be used for each collection created. If null returns Spec with defaultOfferType as set in config.</param>
 /// <returns>The created HashPartitionResolver.</returns>
 public static ManagedHashPartitionResolver InitializeManagedHashResolver(Func <object, string> partitionKeyExtractor, DocumentClient client, Database database, int numCollections, DocumentCollectionSpec collectionSpec)
 {
     // If no collectionSpec used, use a default spec with the offerType (ie: S1, S2, S3) that is specified in config.
     if (collectionSpec == null)
     {
         var hashResolver = new ManagedHashPartitionResolver(partitionKeyExtractor, client, database, numCollections, null, new DocumentCollectionSpec {
             OfferType = defaultOfferType
         });
         client.PartitionResolvers[database.SelfLink] = hashResolver;
         return(hashResolver);
     }
     // If there is a collectionSpec passed as a parameter, use that instead of default.
     else
     {
         var hashResolver = new ManagedHashPartitionResolver(partitionKeyExtractor, client, database, numCollections, null, collectionSpec);
         client.PartitionResolvers[database.SelfLink] = hashResolver;
         return(hashResolver);
     }
 }
Esempio n. 8
0
        /// <summary>
        /// Add a partition (collection) to the consistent hash ring.
        /// </summary>
        /// <returns>The Task object for the asynchronous execution.</returns>
        public async Task <int> AddPartition()
        {
            ManagedHashPartitionResolver currentResolver = (ManagedHashPartitionResolver)this.Client.PartitionResolvers[this.Database.SelfLink];

            return(await this.RepartitionData(currentResolver.PartitionCount + 1));
        }
Esempio n. 9
0
        /// <summary>
        /// Run samples for Database create, read, update and delete.
        /// </summary>
        /// <returns>a Task object.</returns>
        private async Task RunAsync()
        {
            // Let's see how a to use a HashPartitionResolver.
            Console.WriteLine("Running samples with the default hash partition resolver ...");
            Database database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            HashPartitionResolver hashResolver = await this.InitializeHashResolver(database);

            await this.RunCrudAndQuerySample(database, hashResolver);

            // Let's see how to use a RangePartitionResolver.
            Console.WriteLine("Running samples with the default range partition resolver ...");
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            RangePartitionResolver <string> rangeResolver = await this.InitializeRangeResolver(database);

            await this.RunCrudAndQuerySample(database, rangeResolver);

            // Now let's take a look at an example of how to derive from one of the supported partition resolvers.
            // Here we implement a generic hash resolver that takes an arbirary lambda to extract partition keys.
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            HashPartitionResolver customHashResolver = await this.InitializeCustomHashResolver(database);

            await this.RunCrudAndQuerySample(database, customHashResolver);

            // Let's take a look at a example of a LookupPartitionResolver, i.e., use a simple lookup table.
            Console.WriteLine("Running samples with a lookup partition resolver ...");
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            LookupPartitionResolver <string> lookupResolver = await this.InitializeLookupPartitionResolver(database);

            await this.RunCrudAndQuerySample(database, lookupResolver);

            // Now, a "managed" HashPartitionResolver that creates collections, while cloning their attributes like
            // IndexingPolicy and OfferType.
            Console.WriteLine("Running samples with a custom hash partition resolver that automates creating collections ...");
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            ManagedHashPartitionResolver managedHashResolver = this.InitializeManagedHashResolver(database);

            await this.RunCrudAndQuerySample(database, managedHashResolver);

            // Now, a PartitionResolver that starts with one collection and spills over to new ones as the collections
            // get filled up.
            Console.WriteLine("Running samples with a custom \"spillover\" partition resolver");
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            SpilloverPartitionResolver spilloverResolver = new SpilloverPartitionResolver(this.client, database);

            this.client.PartitionResolvers[database.SelfLink] = spilloverResolver;
            await this.RunCrudAndQuerySample(database, spilloverResolver);

            // Now let's see how to persist the settings for a PartitionResolver, and how to bootstrap from those settings.
            this.RunSerializeDeserializeSample(hashResolver);

            // Now let's take a look at how to add and remove partitions to a HashPartitionResolver.
            database = await DocumentClientHelper.GetNewDatabaseAsync(this.client, DatabaseId);

            await this.RepartitionDataSample(database);
        }