Skip to content

CosmosDB Database Provider

Teuz edited this page Apr 3, 2025 · 2 revisions

For easy integration with Cosmos DB, you can use the FeatureManagement.Database.CosmosDB package. This package provides:

  • A default FeatureStore implementation of the IFeatureStore interface, which can be extended as needed.
  • An ICosmosDBConnectionFactory for creating Cosmos DB clients with a default implementation.

Installation

First, install the package:

dotnet add package FeatureManagement.Database.CosmosDB

Basic Setup

Use the default CosmosDBConnectionFactory and configure the services:

services.AddDatabaseFeatureManagement<FeatureStore>()
    .UseCosmosDB(options =>
    {
        options.EndpointUri = "https://your-cosmos-db-endpoint";
        options.AccountKey = "your-cosmos-db-account-key";
        options.DatabaseName = "FeatureManagement";
        options.FeaturesCollectionName = "Features";
        options.FeatureSettingsCollectionName = "FeatureSettings";
        options.UseSeparateContainers = true; // or false if using a single container
    });

Configuration Using IConfiguration

Configure Cosmos DB using appsettings.json:

services.AddDatabaseFeatureManagement<FeatureStore>()
    .UseCosmosDB(Configuration.GetSection("CosmosDBOptions"));

With corresponding appsettings.json:

{
  "CosmosDBOptions": {
    "EndpointUri": "https://your-cosmos-db-endpoint.documents.azure.com:443/",
    "AccountKey": "your-cosmos-db-account-key",
    "DatabaseName": "FeatureManagement",
    "FeaturesCollectionName": "Features",
    "FeatureSettingsCollectionName": "FeatureSettings",
    "UseSeparateContainers": true
  }
}

Custom Connection Factory

Implement your own Cosmos DB connection factory:

public class MyCustomCosmosDBConnectionFactory : ICosmosDBConnectionFactory
{
    private readonly CosmosClient _client;
    private readonly string _databaseName;
    private readonly string _featuresContainerName;
    
    public MyCustomCosmosDBConnectionFactory(string endpoint, string key, string databaseName)
    {
        _client = new CosmosClient(endpoint, key, new CosmosClientOptions
        {
            SerializerOptions = new CosmosSerializationOptions
            {
                PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
            }
        });
        _databaseName = databaseName;
        _featuresContainerName = "Features";
    }
    
    public CosmosClient GetClient()
    {
        return _client;
    }
    
    public Container GetFeaturesContainer()
    {
        return _client.GetContainer(_databaseName, _featuresContainerName);
    }
    
    public Container GetSettingsContainer()
    {
        // Using the same container for features and settings
        return GetFeaturesContainer();
    }
}

Then register your custom factory:

// Register custom factory
services.AddSingleton<ICosmosDBConnectionFactory>(_ => 
    new MyCustomCosmosDBConnectionFactory(
        "https://your-cosmos-db/",
        "your-key",
        "FeatureDatabase"
    ));

// Use the registered factory
services.AddDatabaseFeatureManagement<FeatureStore>()
    .UseCosmosDB();

Container Structure

You can use either a single container for both features and settings or separate containers:

Single Container Approach

With UseSeparateContainers = false, all documents are stored in the same container with a discriminator field:

{
  "id": "feature-123",
  "type": "feature",
  "name": "BetaFeature",
  "requirementType": 1,
  "settings": [
    {
      "id": "setting-456",
      "filterType": "Percentage",
      "parameters": "{\"Value\":50}"
    }
  ]
}

Separate Containers Approach

With UseSeparateContainers = true, features and settings are stored in different containers:

Features container:

{
  "id": "feature-123",
  "name": "BetaFeature",
  "requirementType": 1
}

Feature settings container:

{
  "id": "setting-456",
  "featureId": "feature-123",
  "filterType": "Percentage",
  "parameters": "{\"Value\":50}"
}

Complete Example

public void ConfigureServices(IServiceCollection services)
{
    // Register Cosmos DB feature management with managed identity
    services.AddDatabaseFeatureManagement<FeatureStore>()
        .UseCosmosDB(options =>
        {
            options.EndpointUri = Configuration["CosmosDB:Endpoint"];
            options.DatabaseName = "FeatureFlags";
            options.FeaturesCollectionName = "Features";
            options.UseSeparateContainers = false;
            
            // Use managed identity instead of key authentication
            options.UseTokenCredential = true;
            options.TokenCredential = new DefaultAzureCredential();
        })
        .WithCacheService(cacheOptions =>
        {
            cacheOptions.SlidingExpiration = TimeSpan.FromMinutes(10);
            cacheOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
        });
    
    // Other service registrations...
}

Clone this wiki locally