Skip to content

Add Resilient Fan-Out sample: partial-failure tolerance in a heterogeneous DAG - #790

Open
brainlimitexceeded wants to merge 1 commit into
temporalio:mainfrom
brainlimitexceeded:feature/resilient-fanout-sample
Open

Add Resilient Fan-Out sample: partial-failure tolerance in a heterogeneous DAG#790
brainlimitexceeded wants to merge 1 commit into
temporalio:mainfrom
brainlimitexceeded:feature/resilient-fanout-sample

Conversation

@brainlimitexceeded

Copy link
Copy Markdown

Summary

Adds a sample demonstrating a pattern I couldn't find covered by the existing Child Workflow docs/samples: a fan-out with one critical branch and several best-effort branches, where:

  • Each branch is awaited independently (not via Promise.allOf(...)), so a best-effort failure can't take down a healthy critical branch, or vice versa.
  • Still-running best-effort children are explicitly cancelled via a CancellationScope when the critical branch fails, instead of relying on the default ParentClosePolicy (TERMINATE) — TERMINATE delivers no CanceledFailure, so a child that's already dispatched work to a downstream system gets no chance to react before that work runs on, detached, with nowhere to report back to.
  • Failure is reconciled via Saga with parallel compensation, repurposed for independent, isolated notifications rather than classic "undo what I did" semantics.

The existing Fan-Out pattern doc covers homogeneous fan-out (identical chunks, all-or-nothing). This sample covers the heterogeneous case with partial-failure tolerance, which seems like a natural follow-up.

What's included

  • OnboardingWorkflow + three child workflows (one critical, two best-effort)
  • A runnable Starter covering all three outcomes (happy path, degraded, critical failure)
  • Unit tests for all three outcomes, including verifying reconciliation activities fire independently on critical failure

Test plan

  • ./gradlew :core:test --tests "io.temporal.samples.resilientfanout.OnboardingWorkflowTest" — 3/3 passing
  • ./gradlew spotlessCheck — clean

Happy to adjust scope/naming/domain if this isn't the direction you'd want for this pattern — opening this as a starting point for discussion.

…neous DAG

Adds a sample demonstrating a pattern not covered by the existing
Child Workflow docs/samples: a fan-out with one critical branch and
several best-effort branches, where:

- each branch is awaited independently (not via Promise.allOf(...)),
  so a best-effort failure can't take down a healthy critical branch
  or vice versa
- still-running best-effort children are explicitly cancelled via a
  CancellationScope when the critical branch fails, instead of
  relying on the default ParentClosePolicy (TERMINATE), which kills
  a child with no CanceledFailure to react to
- failure is reconciled via Saga with parallel compensation,
  repurposed for independent, isolated notifications rather than
  classic "undo what I did" semantics

Includes a runnable Starter for all three outcomes and unit tests
covering the happy path, a degraded-but-successful run, and a
critical failure that triggers cancellation + reconciliation.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

3 participants