Skip to content

Comprehensive async-suffixed saga method coverage (GH-3274)#3275

Merged
jeremydmiller merged 1 commit into
mainfrom
feat/saga-async-method-coverage-3274
Jun 29, 2026
Merged

Comprehensive async-suffixed saga method coverage (GH-3274)#3275
jeremydmiller merged 1 commit into
mainfrom
feat/saga-async-method-coverage-3274

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #3274

Background

Issue #3274 re-reports #2578: a saga handler method named with the conventional Async suffix (e.g. HandleAsync, StartAsync) is discovered as a handler but silently never wired as a saga Starting/Existing/NotFound call, so the saga never starts, cascaded continuations are dropped, and the saga parks forever — with no error or warning.

The root cause was an inconsistency: HandlerDiscovery registers both the bare name and the Async-suffixed name as valid handler methods, but SagaChain.findByNames matched the exact Method.Name with no Async variant.

The findByNames fix already shipped on main under #2578 (commit 250f5dad9), so main is not affected by the bug as reported against 5.26.0. What was missing was thorough regression coverage — the existing Bug_2578 test only spot-checks a few names.

What this PR does

Per the issue's "happy to open a PR with a regression test" offer, this adds an async clone of the synchronous saga compliance suite (GuidIdentifiedSagaComplianceSpecs / BasicWorkflow) that exercises every meaningful saga method convention end-to-end, using a genuinely async (Task-returning) body and the Async suffix:

StartAsync, StartsAsync, StartOrHandleAsync, StartsOrHandlesAsync, HandleAsync, HandlesAsync, ConsumeAsync, ConsumesAsync, OrchestrateAsync, OrchestratesAsync, and NotFoundAsync.

Each is verified at two levels:

  • Discovery — the method lands in the correct StartingCalls / ExistingCalls / NotFoundCalls bucket.
  • Runtime — the method is actually invoked, state is persisted/deleted, cascading messages are delivered, the [SagaIdentity] / envelope / message-property id resolution paths all work, and NotFoundAsync runs when the saga is absent.

The end-to-end assertions mirror the cloned synchronous tests (complete, cascading-id-in-header, start_1, start_2, straight update, envelope update, [SagaIdentity] update, indeterminate-id error).

Validation: reverting the findByNames Async match to strict equality fails 25 of the 26 new tests, confirming the coverage is meaningful. With the fix in place all 26 (plus the existing Bug_2578 8) pass.

Docs

Note on 5.x

The bug as filed is against WolverineFx 5.26.0. The main (6.x) line already carries the fix; the 5.0 maintenance branch would need a backport of #2578's one-line findByNames change if a 5.x patch is desired.

🤖 Generated with Claude Code

Issue #3274 re-reports #2578: saga methods named with the conventional
`Async` suffix (e.g. `StartAsync`, `HandleAsync`) are discovered as
handlers but were silently never wired as `Starting`/`Existing`/`NotFound`
saga calls, so the saga never started and cascaded continuations parked
forever with no error.

The `SagaChain.findByNames` fix already shipped on `main` under #2578, but
coverage was minimal. This adds an async clone of the
`GuidIdentifiedSagaComplianceSpecs` / `BasicWorkflow` synchronous suite
that exercises *every* meaningful saga method convention end-to-end with a
genuinely async (Task-returning) body and the `Async` suffix:
`StartAsync`, `StartsAsync`, `StartOrHandleAsync`, `StartsOrHandlesAsync`,
`HandleAsync`, `HandlesAsync`, `ConsumeAsync`, `ConsumesAsync`,
`OrchestrateAsync`, `OrchestratesAsync`, and `NotFoundAsync` — at both the
discovery level (correct Starting/Existing/NotFound bucket) and the
runtime level (method actually invoked, state persisted/deleted, cascades
delivered). Reverting the `findByNames` fix fails 25 of the 26 new tests.

Also expands the saga Method Conventions doc table to list the `Async`
variant of each convention name explicitly, and references #3274 alongside
#2578 in the `findByNames` comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit a9fca37 into main Jun 29, 2026
26 checks passed
This was referenced Jun 29, 2026
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.

Saga handlers with Async suffix are silently not wired (discovered but excluded from Starting/Existing calls)

1 participant