Skip to content

feat(durable-messaging): add hierarchical command and subject contracts - #11282

Open
ReubenBond wants to merge 36 commits into
dotnet:mainfrom
ReubenBond:rb-probable-train
Open

ReubenBond wants to merge 36 commits into
dotnet:mainfrom
ReubenBond:rb-probable-train

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Durable messaging needs a stable application-defined command identity and an explicit protocol subject. This foundation supplies required HierarchicalKey MessageId, sender/receiver identities, ordinal Subject, and an ordinary GC-owned byte[] Payload. The readonly key uses literal-segment construction, canonical parsing/navigation, value equality, and cached hashing. Admission validates external metadata and non-null payloads before mutation.

The envelope is an ordinary non-disposable generated-serializer value. Struct assignment shares its array under the immutable-publication contract: application code keeps command bytes unchanged after direct Send or Deliver. Ordinary Orleans RPC deep copying and deserialization produce independent payload arrays. Serialization, shared dead-letter copying, and mutable-array isolation are verified without custom ownership codecs or RPC argument cleanup.

IInboxHandler.HandleAsync remains non-generic. The context exposes the envelope and explicit synchronous Complete(). From the first shared mutation through method return, handlers perform no awaits; the runtime owns actual journal persistence and acknowledgement. IDurableOutbox.SenderId exposes its owner for upper-layer typed send/reply helpers.

The foundation preserves main's ReadOnlySequence journal storage contract, V1 marker and V0/V1 readers, configured-format fallback, and the merged snapshot policy's 100-append/1 MiB defaults (#11471). The merged general Arc correctness changes (#11474) are preserved exactly from main. Its only included unmerged prerequisites are the current narrowed journal hooks (#11465 at 095bdb4eeb47bc61c7214f68a9df99501b0a8d64) and timer feature (#11464 at 79d7fba537f24fc6e8cce38c9328dd24170d9017). Every journal owner provides the mandatory IJournaledStateManager.Hooks getter and invokes its registered callbacks at the documented operation boundaries. Delegating owners forward the inner list. The standard manager rejects registration changes while persistence is queued or running and preserves actual operation outcomes. Hook implementations complete without awaiting initialization, persistence, or disposal on their own owner, whose work is serialized behind the current callback. Distinct pre-commit and post-commit exception types preserve the cause and outcome; their operation remains in the diagnostic message. The approved implementer-contract break has exactly two package-scoped CP0006 Hooks-property suppressions, one per target framework; the public delegate adapter is removed. Timer ticks use one Idle/Busy/Disposed phase, an eagerly created provider timer, and an explicit context-free message-construction path.

Abandoned RPC and dictionary value ownership work (#11468, #11469) is absent from implementation, generated APIs, and tests. Independent Arc codecs (#11463), dependency caches (#11467), and the narrowed pool-only improvement (#11470) are outside this layer. The closed format extraction (#11466) is excluded. Obsolete pool-budget and hook-adapter snippets are removed, while main's snapshot configuration and interface-based hook registration remain current.

Layer 1 of 4. Rebased onto main 42682376d80e1176a952ba13aa2de25a307b576e; published head ef6a16b0ead84f52a53896cece8e90ff168fe6c5. Review this layer. Receiver processing follows in #11284, outgoing delivery in #11285, and typed helpers/hosting/docs/samples in #10693.

Copilot AI lite review requested due to automatic review settings September 16, 2026 21:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Five unresolved findings remain, including two critical HierarchicalKey issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity · 1 Medium severity

Open (3)
What changed in this PR

Adds durable messaging contracts, routing helpers, and Journaling lifecycle support for future inbox/outbox runtime layers.

Changes:

  • Adds envelopes, hierarchical keys, delivery outcomes, options, and inbox/outbox interfaces.
  • Adds routing handlers and Journaling observer/participant support.
  • Adds tests, API surfaces, and project/solution wiring.
File Reviewed change
test/​Orleans.Journaling.Tests/​StateManagerTests.cs Tests observer boundaries and recovery fencing.
test/​Orleans.Journaling.Tests/​JournaledGrainParticipantTests.cs Tests participant lifecycle integration.
test/​Orleans.DurableMessaging.Tests/​Orleans.DurableMessaging.Tests.csproj Configures messaging contract tests.
test/​Orleans.DurableMessaging.Tests/​Contracts/​HierarchicalKeyTests.cs Tests hierarchical key behavior.
test/​Orleans.DurableMessaging.Tests/​Contracts/​HandlerRoutingContractTests.cs Tests routing and typed handlers.
test/​Orleans.DurableMessaging.Tests/​Contracts/​DurableEnvelopeContractTests.cs Tests envelope serialization and validation.
test/​Orleans.DurableMessaging.Tests/​Contracts/​DeliveryAndOptionsContractTests.cs Tests delivery results and options.
src/​Orleans.Journaling/​JournaledStateManager.cs Implements observers and recovery generations.
src/​Orleans.Journaling/​IJournaledStateObserver.cs Defines observer callbacks.
src/​Orleans.Journaling/​IJournaledStateManager.cs Adds observer registration. Finding: moderate (1 vote) — null observers are not validated before the compatibility default throws NotSupportedException.
src/​Orleans.Journaling/​IJournaledGrainParticipant.cs Defines grain participants.
src/​Orleans.Journaling/​DurableGrain.cs Initializes participants during activation.
src/​Orleans.DurableMessaging/​RoutePrefixHandler.cs Implements prefix routing.
src/​Orleans.DurableMessaging/​RouteKeyHandler.cs Implements exact routing.
src/​Orleans.DurableMessaging/​README.md Documents messaging contracts.
src/​Orleans.DurableMessaging/​Orleans.DurableMessaging.csproj Defines the intermediate project.
src/​Orleans.DurableMessaging/​InboxHandlerSelectionContext.cs Provides read-only selection context.
src/​Orleans.DurableMessaging/​InboxHandlerContext.cs Implements handler messaging context.
src/​Orleans.DurableMessaging/​IInboxHandlerContext.cs Defines handler context APIs.
src/​Orleans.DurableMessaging/​IInboxHandler.cs Defines typed and untyped handlers.
src/​Orleans.DurableMessaging/​IDurableOutbox.cs Defines outbox contracts.
src/​Orleans.DurableMessaging/​IDurableInboxExtension.cs Defines the grain delivery extension.
src/​Orleans.DurableMessaging/​IDurableInbox.cs Defines inbox contracts.
src/​Orleans.DurableMessaging/​HierarchicalKey.cs Implements hierarchical correlation keys. Findings: moderate (3 votes) — null overload inputs can produce NullReferenceException; critical (1 vote) — child-key enumeration reverses chain order; critical (1 vote) — HashCode.AddBytes is unavailable for the net8.0 target.
src/​Orleans.DurableMessaging/​DurableEnvelopeData.cs Stores deferred serialized data.
src/​Orleans.DurableMessaging/​DurableEnvelopeBuilder.cs Builds serialized envelopes. Finding: moderate (1 vote) — default SenderId can create an invalid deduplication identity.
src/​Orleans.DurableMessaging/​DurableEnvelope.cs Defines the envelope model.
src/​Orleans.DurableMessaging/​DeliveryStatus.cs Defines delivery statuses.
src/​Orleans.DurableMessaging/​DeliveryResult.cs Defines delivery outcomes.
src/​Orleans.DurableMessaging/​CorrelationHandler.cs Implements correlation routing.
src/​Orleans.DurableMessaging/​Configuration/​DurableInboxOptions.cs Defines validated messaging options.
src/​api/​Orleans.Journaling/​Orleans.Journaling.cs Updates the Journaling API surface.
src/​api/​Orleans.DurableMessaging/​Orleans.DurableMessaging.cs Adds the messaging API surface.
Orleans.slnx Registers source and test projects.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Orleans.DurableMessaging/HierarchicalKey.cs Outdated
Comment thread src/Orleans.DurableMessaging/HierarchicalKey.cs Outdated
Comment thread src/Orleans.DurableMessaging/HierarchicalKey.cs Outdated
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request Current main Variance
Lines 83.51% (119,043 / 142,552) 83.40% (118,474 / 142,050) +0.1054 pp
Branches 73.12% (35,494 / 48,540) 72.99% (35,240 / 48,282) +0.1353 pp

Report-only conclusion: improved.

The current-main baseline is commit 42682376d8 and uses the same reviewed coverage matrix.

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.

Coverage details

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved recovery-generation and envelope-builder findings remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 High severity · 1 Medium severity

Open (4)
Previously missed (1)

In code that hasn't changed since last review

Low severity Fix article in hierarchical-key validation comment

src/​Orleans.DurableMessaging/​HierarchicalKey.cs:291

The comment uses “an segment separator”, which is grammatically incorrect and makes the validation explanation less clear; change it to “a segment separator”.

Comment thread src/Orleans.Journaling/JournaledStateManager.cs Outdated
Copilot AI review requested due to automatic review settings September 16, 2026 22:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The moderate CorrelationKey nullability issue remains unresolved; the additional comment typo is a minor nit.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Low severity

Open (1)
Resolved since last review (4)

Comment thread src/Orleans.DurableMessaging/HierarchicalKey.cs Outdated
Copilot AI review requested due to automatic review settings September 16, 2026 23:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Two moderate validation issues remain in DurableEnvelopeBuilder.

Review effort: Lite
Findings: None

Resolved since last review (2)

Copilot AI review requested due to automatic review settings September 17, 2026 00:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved contract validation, API compatibility, manifest, and Journaling behavior findings remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity

Open (2)

Comment thread src/Orleans.DurableMessaging/IDurableInboxExtension.cs
Comment thread src/Orleans.DurableMessaging/DurableEnvelopeBuilder.cs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

A moderate nullable-correlation API issue remains unresolved across a broad contract and journaling change.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Copilot AI review requested due to automatic review settings September 17, 2026 03:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical shutdown fault-reporting and moderate contract issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread src/Orleans.Journaling/JournaledStateManager.cs Outdated
Copilot AI review requested due to automatic review settings September 17, 2026 07:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

// A queued or running callback keeps its turn; changes schedule work after it completes.
if (_state == TimerState.Idle)
{
queueTick = ScheduleNextTick();

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants