-
Notifications
You must be signed in to change notification settings - Fork 2
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
FeatureStoreimplementation of theIFeatureStoreinterface, which can be extended as needed. - An
ICosmosDBConnectionFactoryfor creating Cosmos DB clients with a default implementation.
First, install the package:
dotnet add package FeatureManagement.Database.CosmosDBUse 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
});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
}
}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();You can use either a single container for both features and settings or separate containers:
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}"
}
]
}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}"
}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...
}