You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Journaling API mixes application state management with the state-machine protocol and journal ownership. The existing GetOrCreateState helpers require the implementation interface, while the public durable collection interfaces expose application operations. Programmatic access and keyed dependency injection also follow different construction paths.
Solution
Introduce the grain-facing IDurableStateManager with typed GetOrAddState, lookup, and WriteStateAsync, plus helpers for dictionaries, lists, queues, sets, values, persistent state, and task-completion sources. Keyed injection and programmatic access converge on the same named state component. Register custom grain-state implementations through IServiceCollection.AddStateMachine<TState, TImplementation>, with constructor-injection and name-aware factory overloads.
Rename IJournaledState to IStateMachine and use WritePendingEntries/WriteSnapshot for its output methods. Keep IJournaledStateManager as an independent journal-owner contract: explicit state-machine registration and lookup, initialization, writes, deletion, disposal, and diagnostics. Remove unused DeepCopy and IDurableNothing, and align catalog, metadata, hosting, and persistent-state adapter names.
The default grain manager implements both contracts as one activation-scoped instance. It reuses the activation's services and enrolls during grain-bound construction. Ordinary Grain and IGrainBase implementations can inject the application interface directly, and synchronous activation-setup hooks can resolve managers and state components. The activation scope owns DI-created components and dependencies. Declare state components during construction or synchronous setup so recovery completes at SetupState before application use.
IJournaledStateManagerFactory.CreateStandalone(JournalId) returns a journal owner for explicitly supplied IStateMachine components. The caller constructs and registers those components, initializes the owner, writes state, and disposes the owner when finished. Component instances and their dependencies remain caller-owned; the journal owner releases its own processing resources. Standalone owners use the host's shared journal services, as DurableJobs does, while DI-backed GetOrAdd belongs to the grain-facing application interface.
Registration closes synchronously when initialization begins; recovery, queued failure barriers, and state retirement retain their existing guarantees. Update DurableJobs, provider consumers, documentation, snippets, samples, and the generated public API. Regenerate package/API-specific compatibility suppressions for the intentional alpha API changes.
Rationale
Durable* names describe application state, IStateMachine describes its implementation protocol, and Journal* names describe persistence infrastructure. Ordinary activation-scoped DI caching supplies grain manager identity; standalone components use explicit caller-owned construction. This keeps the two ownership models separate.
Built-in grain-state constructors retain registration to support .NET's native open-generic keyed DI registrations. The manager owns registry admission and resolves the canonical keyed instance. Custom constructors leave registration to the manager.
Persisted state names, stream identities, command tokens, format-key values, serialization IDs, and provider metadata keys remain stable.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
The broad API, lifecycle, and provider refactor requires final human review.
Review effort: Lite Findings: None
What changed in this PR
Refactors Orleans Journaling to separate durable application state APIs from journal state-machine infrastructure while updating providers, Durable Jobs, tests, documentation, samples, and public APIs.
Changes:
Adds IDurableStateManager and typed durable-state helpers.
Renames state-machine, catalog, metadata, and hosting APIs.
Updates integrations, providers, tests, benchmarks, samples, and documentation.
The newest successful coverage run tested 39ea499, not current main 598c0d2.
Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities.
The comparison remains report-only while normal line and branch variance is calibrated.
Correct metadata-less recovery format fallback documentation
src/Orleans.Journaling/README.md:66
This fallback description contradicts the implementation: JournaledStateManager.ProcessRecoveryBuffer uses the configured write format when metadata?.FormatKey is absent (JournaledStateManager.cs:802-804), and Recovery_MetadataLessJournal_UsesConfiguredFormat verifies that behavior. Saying metadata-less data is always treated as Orleans Binary can lead operators to configure a migration incorrectly; document the configured-format fallback instead. The same claim is repeated later in this README and should be corrected there too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Journaling API mixes application state management with the state-machine protocol and journal ownership. The existing
GetOrCreateStatehelpers require the implementation interface, while the public durable collection interfaces expose application operations. Programmatic access and keyed dependency injection also follow different construction paths.Solution
Introduce the grain-facing
IDurableStateManagerwith typedGetOrAddState, lookup, andWriteStateAsync, plus helpers for dictionaries, lists, queues, sets, values, persistent state, and task-completion sources. Keyed injection and programmatic access converge on the same named state component. Register custom grain-state implementations throughIServiceCollection.AddStateMachine<TState, TImplementation>, with constructor-injection and name-aware factory overloads.Rename
IJournaledStatetoIStateMachineand useWritePendingEntries/WriteSnapshotfor its output methods. KeepIJournaledStateManageras an independent journal-owner contract: explicit state-machine registration and lookup, initialization, writes, deletion, disposal, and diagnostics. Remove unusedDeepCopyandIDurableNothing, and align catalog, metadata, hosting, and persistent-state adapter names.The default grain manager implements both contracts as one activation-scoped instance. It reuses the activation's services and enrolls during grain-bound construction. Ordinary
GrainandIGrainBaseimplementations can inject the application interface directly, and synchronous activation-setup hooks can resolve managers and state components. The activation scope owns DI-created components and dependencies. Declare state components during construction or synchronous setup so recovery completes atSetupStatebefore application use.IJournaledStateManagerFactory.CreateStandalone(JournalId)returns a journal owner for explicitly suppliedIStateMachinecomponents. The caller constructs and registers those components, initializes the owner, writes state, and disposes the owner when finished. Component instances and their dependencies remain caller-owned; the journal owner releases its own processing resources. Standalone owners use the host's shared journal services, as DurableJobs does, while DI-backedGetOrAddbelongs to the grain-facing application interface.Registration closes synchronously when initialization begins; recovery, queued failure barriers, and state retirement retain their existing guarantees. Update DurableJobs, provider consumers, documentation, snippets, samples, and the generated public API. Regenerate package/API-specific compatibility suppressions for the intentional alpha API changes.
Rationale
Durable*names describe application state,IStateMachinedescribes its implementation protocol, andJournal*names describe persistence infrastructure. Ordinary activation-scoped DI caching supplies grain manager identity; standalone components use explicit caller-owned construction. This keeps the two ownership models separate.Built-in grain-state constructors retain registration to support .NET's native open-generic keyed DI registrations. The manager owns registry admission and resolves the canonical keyed instance. Custom constructors leave registration to the manager.
Persisted state names, stream identities, command tokens, format-key values, serialization IDs, and provider metadata keys remain stable.
Microsoft Reviewers: Open in CodeFlow