Is your feature request related to a problem? Please describe.
Currently, UseCosmosDbPersistence() requires a CosmosClient instance to be provided at service registration time:
services.AddWorkflow(options =>
{
options.UseCosmosClientPersistence(cosmosClientInstance, databaseId);
});
This forces consumers to either:
- Build the
CosmosClient early during configuration phase (anti-pattern)
- Use
services.BuildServiceProvider() to resolve it from DI (performance penalty, creates duplicate singletons)
- Resort to manual registration of internal types like
CosmosDbPersistenceProvider using UsePersistence() factory
The issue is that CosmosClient is typically registered as a singleton in the DI container, but UseCosmosDbPersistence() cannot access it from the service provider since the configuration action runs before the container is built.
Current overloads of UseCosmosDbPersistence() force duplication of CosmosClient instances and don't support reusing existing DI registrations:
- Connection string overload - Creates its own client, ignoring existing DI registration with custom auth/serialization setup
- CosmosClient instance overload - Requires early instantiation, breaking DI patterns and causing duplicate singletons
- Endpoint + TokenCredential overload - Hardcodes specific auth method, preventing reuse of existing configured client
Most applications already register CosmosClient for other services (health checks, custom repositories, etc.) with specific authentication methods (managed identity, service principal, connection string). WorkflowCore should reuse this existing registration rather than creating duplicate connections with potentially different auth configurations.
Describe the solution you'd like
Add an overload to UseCosmosDbPersistence() that accepts a factory delegate Func<IServiceProvider, CosmosClient> instead of a direct instance:
services.AddWorkflow(options =>
{
// New overload - CosmosClient resolved from DI when first needed
options.UseCosmosDbPersistence(
sp => sp.GetRequiredService<CosmosClient>(),
databaseId,
storageOptions); // Optional: CosmosDbStorageOptions
});
This would internally use UsePersistence() with a factory that resolves CosmosClient from the service provider, aligning with DI best practices and matching the pattern already available for other persistence providers.
Describe alternatives you've considered
- Manual registration using
UsePersistence() - This works but requires consumers to reference internal types (CosmosClientFactory, CosmosDbProvisioner, CosmosDbPersistenceProvider) that are implementation details and may break in future versions:
options.UsePersistence(sp =>
{
var cosmosClient = sp.GetRequiredService<CosmosClient>();
var clientFactory = new CosmosClientFactory(cosmosClient);
var provisioner = new CosmosDbProvisioner(clientFactory, new CosmosDbStorageOptions());
return new CosmosDbPersistenceProvider(clientFactory, databaseId, provisioner, new CosmosDbStorageOptions());
});
Additional context
This pattern is already established in other parts of .NET ecosystem (e.g., AddDbContext() accepts Action<IServiceProvider, DbContextOptionsBuilder>). The WorkflowCore library already supports factory-based registration via UsePersistence(Func<IServiceProvider, IWorkflowPersistenceProvider>), so extending this to the Cosmos DB provider would be a natural and consistent enhancement.
Environment:
- WorkflowCore 3.17.0
- WorkflowCore.Providers.Azure 3.17.0
- Microsoft.Azure.Cosmos 3.58.0
Is your feature request related to a problem? Please describe.
Currently,
UseCosmosDbPersistence()requires aCosmosClientinstance to be provided at service registration time:This forces consumers to either:
CosmosClientearly during configuration phase (anti-pattern)services.BuildServiceProvider()to resolve it from DI (performance penalty, creates duplicate singletons)CosmosDbPersistenceProviderusingUsePersistence()factoryThe issue is that
CosmosClientis typically registered as a singleton in the DI container, butUseCosmosDbPersistence()cannot access it from the service provider since the configuration action runs before the container is built.Current overloads of
UseCosmosDbPersistence()force duplication ofCosmosClientinstances and don't support reusing existing DI registrations:Most applications already register
CosmosClientfor other services (health checks, custom repositories, etc.) with specific authentication methods (managed identity, service principal, connection string). WorkflowCore should reuse this existing registration rather than creating duplicate connections with potentially different auth configurations.Describe the solution you'd like
Add an overload to
UseCosmosDbPersistence()that accepts a factory delegateFunc<IServiceProvider, CosmosClient>instead of a direct instance:This would internally use
UsePersistence()with a factory that resolvesCosmosClientfrom the service provider, aligning with DI best practices and matching the pattern already available for other persistence providers.Describe alternatives you've considered
UsePersistence()- This works but requires consumers to reference internal types (CosmosClientFactory,CosmosDbProvisioner,CosmosDbPersistenceProvider) that are implementation details and may break in future versions:Additional context
This pattern is already established in other parts of .NET ecosystem (e.g.,
AddDbContext()acceptsAction<IServiceProvider, DbContextOptionsBuilder>). The WorkflowCore library already supports factory-based registration viaUsePersistence(Func<IServiceProvider, IWorkflowPersistenceProvider>), so extending this to the Cosmos DB provider would be a natural and consistent enhancement.Environment: