feat(journaling): select journal providers per grain type
Summary
Enable a grain type to select a registered named journal storage provider. All journaled state in an activation should use that provider through the activation's shared journaled state manager.
Follow-up to #11275, which introduces named journal provider registration and keyed storage, catalog, and state-manager factory services.
Motivation
Applications need different grain types to use independent journal namespaces, accounts, or backends while retaining a default provider for other types. A grain-type declaration should connect those named registrations to ordinary DurableGrain usage and injected durable state.
Today, DurableGrain resolves the activation-scoped, unkeyed IJournaledStateManager. Its registration resolves the unkeyed IJournalStorageProvider, supplied by the Default binding. Named factories support explicit journal consumers; grain activations currently select the default provider.
Proposed behavior
- Provide a declarative grain-type provider selection mechanism, integrated with Orleans grain-type metadata and existing configuration conventions. Evaluate the existing storage-provider attribute conventions when choosing the public API.
- Resolve the selected named provider when creating the activation-scoped journaled state manager. Keep the selection consistent across silos and stable for the activation's lifetime.
- Use the same manager and selected storage for
DurableGrain.StateManager, injected durable values and collections, and journaling-backed persistent state. - Preserve
Defaultselection for grain types without an explicit selection, including its existing unnamed backend-options behavior. - Report an invalid or unregistered selection clearly, identifying the grain type and provider name, before accessing journal data.
- Preserve journal identity derivation and the provider registration's options and lifecycle semantics.
Acceptance criteria
- Two grain types can select different providers, including two named providers of the same backend, and recover their respective state after deactivation and reactivation.
- Grain types without an explicit selection continue to use
Default, independent of named-provider registration order. - A grain's base-class operations and all injected journaled state share the same activation-scoped manager and selected provider.
- Invalid provider selections produce contextual configuration errors rather than selecting another provider.
- Regression coverage verifies provider isolation, default compatibility, activation lifecycle/recovery, and invalid selections on supported target frameworks.
- Public APIs have XML documentation and regenerated API surfaces where applicable.
- Documentation includes a compilable per-grain-type configuration example and explains that recovery reads the selected physical namespace. Changing the selection for a grain type with existing journals requires a deliberate data migration or cutover strategy.
Implementation entry points
src/Orleans.Journaling/HostingExtensions.cs: activation-scoped manager registration and named provider bindings.src/Orleans.Journaling/DurableGrain.cs: manager resolution and grain lifecycle participation.src/Orleans.Journaling/JournaledStateManager.cs: grain journal identity and provider-backed storage creation.
Keep the change focused on selecting providers for grain types; retain the named-provider registration behavior established by #11275.
Source: dotnet/orleans