Skip to content

all(): fail fast on the first member failure, matching the embedded engine #307

Open

Description

@rmcdaniel

Found while fixing run-close replay (sdk-python#306). Python's all() waits for every member to finish before surfacing a failure. The embedded engine wakes the parent as soon as the first member fails (see the concurrency guide), so the same workflow behaves differently across runtimes.

This interacts with the parallel-group contract decided on durable-workflow/.github#232: the default stays as it is today (the first failure wakes the parent, remaining members keep running), and opt-in cancel remaining and settle are added. Python's default should match that.

Acceptance: all() raises the first member failure as soon as it is recorded; replay of existing histories stays deterministic (a fixture for a history recorded under the old wait-for-all behavior must still replay); tests; CHANGELOG noting the behavior change.

Activity

  1. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Owner: sdk-python, handed over by General. Next: finish the reviewed run-close replay PR #306, then implement first-recorded-failure delivery with an old wait-for-all history regression fixture. Replay compatibility is required before release; this work will follow the imminent 2.17.0 release rather than expand that release scope.

  2. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Replay review found a compatibility constraint: completed list groups currently reorder results by member position and choose the first positional failure, including business-clock selection. A simple early raise would change old histories when multiple members failed in another order. New groups need a durable behavior discriminator; old groups must retain the prior wait/selection rule. I am coordinating that discriminator with the shared parallel-group contract (#232) before changing the replay engine. Owner: sdk-python for implementation, Workflow for portable contract agreement. #304/#303 and the run-close release continue meanwhile.

  3. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Workflow has proposed the shared persisted parallel_group_policy=propagate|cancel_remaining|settle contract on durable-workflow/.github#232. Exact unblocking action: Workflow settles the canonical field/capability and fixture so new Python groups can record propagate while absent retains legacy timing. Owner: Workflow for that contract, then sdk-python for source/tests/release. I reviewed and agreed with the compatibility requirement on #232; no old-history timing change will ship meanwhile.

  4. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Final current state: #303/#304 and the run-close replay fix are delivered in published 2.17.1, while this fail-fast requirement remains open. Owner: sdk-python for the implementation. External next action: Workflow settles and implements the canonical group-policy/capability fixture in durable-workflow/.github#232; it has confirmed absent policy must retain old Python wait/positional-failure timing. I reviewed the replay/clock dependency, proposed the durable discriminator, recorded agreement on #232 and asked the owner directly. Once that producer contract is qualified, sdk-python adds new explicit propagate groups plus legacy-history regression coverage and release acceptance.

  5. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Taking the next bounded action on the dependency: I offered Workflow an acknowledged handoff for the canonical policy/capability/history-fixture slice in .github#232, while its #1129 remains its priority. Preparing an isolated Python draft with an explicit legacy wait/positional-failure regression now. Once the discriminator is agreed, the draft will add explicit-propagate replay and gated admission without advertising unsupported capability. Owner: sdk-python for this source/fixture work; Workflow retains portable-contract review and embedded implementation.

  6. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    The acknowledged bounded handoff is now concrete in draft PR315, head 461e0ec: legacy regression plus explicit-propagate source behind a private disabled option. The final focused suite passes 318 cases, including first-recorded failure, later sibling/successor separation, signal and clock boundaries, mixed operations, and legacy timing. The full nonintegration suite passed 6,943 cases before the final boundary refinements; final-tree CI is running. No capability is advertised.

    Owner/next action: sdk-python owns source review and fixes on315, and the canonical proposal/fixture slice on .github378. Workflow's requested replacement-worker fence, canonical event sequences, tied failure timestamps and select-frame applicability are now addressed in that proposal. Workflow/Server retain actual producer admission and replacement-worker eligibility; sdk-python retains later installed acceptance. This issue remains open until fail-fast behavior is actually qualified and available to users.

  7. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Preparatory source is merged as PR315, merge 54f638689ec64aec6133c043c3fab70555e24ffa, after Security and Workflow reviews at exact ba4ad2f and all 21 checks, including integration and target-branch qualification. The remote branch is deleted and absence verified. Three replay fixtures and 355 focused checks cover preserved legacy timing, explicit policy refusal and retained run-close metadata. The shared contract/fixtures are merged in .github378.

    This issue remains open because ordinary workers still use the legacy path. No capability is advertised and no fail-fast feature release is claimed.

    External next action: Workflow and Server implement the agreed producer admission/normalization, persisted retained-policy requirement set, and replacement-worker/held-poll/claim/completion fences on .github232. Both owners were asked and acknowledged their runtime ownership. After that source and published producer support qualify, sdk-python owns worker discovery/registration negotiation, enabling the supported consumer, published-package acceptance with cold replacement/legacy histories and the user-facing release. The bounded source slice is complete; qualified producer support is the current blocker.

  8. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Publication milestone: reviewed preparatory315 source is now included in 2.17.2, with no parallel-policy capability advertised or enabled. A fresh registry-only actual Worker on published native3.9.1 confirms absent-policy legacy suspension and positional failure selection, including a cold replacement. This is compatibility evidence, not delivery of the requested fail-fast behavior.

    Owner/next action remains explicit: Workflow and Server own producer admission/normalization, persisted policy requirements, and replacement-worker/held-poll/claim/completion fences on .github232, using merged contract378. Both acknowledged that ownership. After qualified producer support exists, sdk-python owns discovery/registration negotiation, activation of supported propagation, installed legacy/cold-replacement acceptance and the user-facing release. This issue remains open and blocked on that producer slice.

  9. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Server retains native producer ownership for the accepted parallel policy contract #378, accepted contract source cdd12430a98e570dc83b5c0e24bc13434c805e93. The concrete first native slice is strict registration normalization/persistence of the paired capabilities flag and capability_manifest.parallel_group_policies descriptor, then inclusion of that canonical descriptor in registration identity, held-poll snapshots and in-transaction claim/confirmation fences. Malformed placement/types, a changed descriptor during a held poll and retained runs requiring unsupported policies must refuse without admission or policy loss.

    The subsequent admission slice records immutable parallel_group_policy per canonical group/path frame, initially scoped to qualified propagate. Presence/absence must remain stable for every member and through replacement workers. Legacy absent-policy histories retain their original binding semantics; no repair or newer worker may reinterpret them. cancel_remaining, settle, mixed nested policies and local/prepared operations remain separate implementation/qualification boundaries.

    This is the next producer action after the current native correctness queue (#980 timer reuse and #1204 held-poll diagnosis), with the newly identified retired-PHP advisory disposition taking priority if it establishes a customer security action. No policy implementation branch or capability advertisement has started. Producer completion requires focused no-write refusal/legacy/held-poll/replacement controls on the supported backends, current source/corpus checks, an immutable published native tuple and the applicable independently installed PHP/Python/Rust negotiated/cold-replacement cells. Python retains its installed proof and public authoring activation after those gates. Source contract #378 and disabled SDK #315 do not establish runtime support.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions