Skip to content

A child resolution attached to a leased parent task can leave the parent without a resume #962

Closed

Description

@rmcdaniel

Delivered

The final published Server 2.11.8 / Core 2.15.12 passes the reported raw-worker-HTTP child/leased-parent interleaving on SQLite and PostgreSQL 17.11. Both produce an immediate distinct task containing the late outcome, and the parent completes. No further PHP Server release is required or planned. Core source qualification and the original installed-library controls remain below; #947 owns the separate native Nexus follow-through.

Found while checking native parity for Server #325, against published Server 2.11.7 (Core 2.15.7).

Behavior

DefaultWorkflowTaskBridge::dispatchParentResumeTasksForRun records a child's resolution and reuses the parent's first ready or leased workflow task instead of creating one. When that task is leased, the worker holding it has already received its history and never sees the new resolution.

Reproduced over raw worker HTTP on protocol 1.20, against SQLite, with the maintenance repair pass running every second:

  1. A parent starts two children. Child A completes, and the parent worker leases the resume task.
  2. Child B completes while that task is leased. PHP attaches B's resolution to the leased task.
  3. The worker completes the task with a 3600-second timer, having never seen B's result. The answer is 200 waiting.
  4. Afterwards:
    • the parent has no open workflow task;
    • no follow-up task is created;
    • the parent is described as waiting on its timer;
    • both child waits are resolved, and B's has no task (task_backed=0, task_id=null).
  5. Nothing changed after more than 60 seconds of repair passes.

B's result stays unconsumed until the timer fires an hour later. A parent whose remaining wait has no deadline would never wake.

When the parent's task is ready (not yet leased), the reuse is safe: the parent's next poll carries both resolutions.

Expected

A resolution recorded after the parent's task was leased should produce a follow-up task when that task completes without consuming it. Alternatively, it should get its own resume task, as the native server does.

Native

The native server is unchanged by this report. It gives each child resolution its own resume task outside cooperative cancellation, so a parent cannot lose a wake-up. Its port log documents this as an intentional difference.

🤖 Generated with Claude Code

Prior source delivery

Core 2.15.10 is published through merged #963 at e2b199673d087fd278628db066e215217eec61cb. Full source quality and all four database-driver race/corpus cells pass. Normal published verification passes all 17 jobs. Actual stock Composer consumers pass the reported raw worker HTTP interleaving on SQLite and PostgreSQL 17.11, with all 1,010 runtime/resource/metadata files matching the immutable tag.

At the time of the original source delivery, published Server 2.11.7 embedded Core 2.15.7. The exact Core pin update Server PR #892 merged through the protected queue as 08c7adab2fba84d4e22204421e1a8822bc9c7c71 at 2026-10-31 11:14:58 UTC, exact reviewed tree 5c77af087191dfb37cb3d0f076722151cc2abdd7. Its local child/queue/Nexus/corpus checks pass 115 tests / 1,785 assertions; Bridge contracts pass 21/255 with two expected SQLite skips; installed Core 1,010 bytes and three release contracts pass. PR and queue qualification both pass the full 3,445-test / 74,926-assertion suite and candidate image/TLS/logging checks. Normal main PHP/Sonar/topology and the remaining checks now pass. The final PHP Server 2.11.8 is now published with Core 2.15.12 and includes this correction. The operator has stopped further PHP Server releases. That installed-image acceptance is now complete on SQLite and PostgreSQL 17.11, as recorded above. No new PHP Server publication is planned. #947 separately owns installed host-query/Nexus acceptance.

Activity

  1. rmcdaniel commented on Oct 30, 2026

    @rmcdaniel
    MemberAuthor

    General accepts the published-PHP handoff and owns the Core correction plus published Server follow-through. Current Core 2.15.8 still selects either a ready or leased parent task in dispatchParentResumeTasksForRun; the already-qualified Server 2.11.8 source therefore does not repair this defect. Native/shared/frozen qualification remains with its owner.

    Next: turn the two-child/leased-history sequence into a failing bridge regression, preserve safe ready-task coalescing and single-run execution, then prove that a late child result is delivered promptly after stale completion. Include terminal-parent, child failure/cancellation and repeated-completion controls, normal quality checks and actual published raw-worker-HTTP acceptance before closing. Projection repair evidence is separate from durable task delivery; no fix or publication is claimed yet.

  2. added
    bugSomething isn't working
    kind:defectA public product behavior is incorrect
    priority:P1High-priority product or release risk
    on Oct 30, 2026
  3. rmcdaniel commented on Oct 31, 2026

    @rmcdaniel
    MemberAuthor

    Core 2.15.10 is published and installed-package acceptance passes. Release, source e2b199673d087fd278628db066e215217eec61cb, from protected #963. All final PR checks and all 29 main checks passed. Normal published-package verification passed all 17 jobs, including the 16 actual Laravel/PHP upgrade journeys.

    At 2026-10-31 10:14 UTC, two source-free disposable consumers started from the immutable published Server 2.11.7 amd64 image (be7c2288ff935396262d743590530b204fac11b76582e56a525cc81a8da840d3). Each used ordinary Composer to install public Core 2.15.10: zero installs, one Core update, zero removals; normal audit reported zero advisories. All 1,010 runtime/resource/metadata files exactly match the release tag, with no missing, additional or mismatched files. The bridge class is loaded from the installed vendor package.

    The real HTTP control API v2 / worker protocol 1.20 passes the reported interleaving on SQLite and PostgreSQL 17.11. Parent starts two children; A completes; the parent claims history containing only A; B completes during that lease; parent completes into an unrelated 3,600-second timer; an immediate distinct follow-up task contains both outcomes and identifies B; the parent completes successfully. Elapsed time: SQLite 1.404s, PostgreSQL 1.797s. Synthetic worker registrations were seeded locally; this is worker-task HTTP acceptance, not worker-registration acceptance. Avro values use the stock published serializer.

    Full source qualification remains recorded on #963: ECS/PHPStan, full unit/coverage/PG feature suites and all four database-driver race/corpus cells pass with the original gates. The one accepted maintainability finding and the initial failed qualification attempts remain disclosed there.

    These are Composer-updated consumers of the published library, not a newly published Server image. Published Server 2.11.7 still embeds Core 2.15.7. This issue stays open for the Server pin and actual published-image follow-through; #947 retains the separate Nexus/host-query acceptance.

  4. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Native follow-up for reference: durable-workflow/server#915 makes the native server reuse a parent's ready workflow task for a child's resolution, matching 2.11.7's safe coalescing. The new child-open-parent-task parity fixture records that against published 2.11.7. Beside only a leased task, native keeps giving the resolution its own resume task, so the leased-lease loss reported here can't happen on native. Native creates that task at once rather than as 2.15.10's follow-up after the lease completes; we'll compare again when a published Server carries Core 2.15.10. I re-confirmed the 2.11.7 loss locally with the maintenance loop stopped: after the stale lease completes, no parent task is claimable and one workflow:v2:repair-pass changes nothing.

  5. rmcdaniel commented on Nov 2, 2026

    @rmcdaniel
    MemberAuthor

    The final published Server 2.11.8 / Core 2.15.12 now passes this issue's installed-image acceptance on SQLite and PostgreSQL 17.11, completing the remaining delivery step. Image index sha256:3848d5d5cd1b23bd2881e3fdecea64cc44b72e6fb812e577c2db6d0872d065dd, Server source fa3fc2f2f6b8935ea4a6eea47f6a9221e2adafff, Core source 7c80ffccdb6ab6e6ace8339618a9d6f1d6d9432f.

    The actual control API v2 / worker protocol 1.20 sequence passes on both backends: parent starts two children; A completes; the parent leases history containing only A; B completes during that lease; the stale parent task completes into an unrelated 3,600-second timer; an immediate distinct follow-up task contains both child outcomes and identifies B; the parent completes. Elapsed time was 2.135 s on SQLite and 2.020 s on PostgreSQL.

    This uses the existing unmodified image and its installed vendor package, with normal bootstrap and synthetic disposable worker registrations. No Composer update, application/library overlay, new release or worker-registration acceptance is claimed. The root Composer default version and Core path-repository locator are not used as Git source identity; immutable image labels identify the published source tuple.

    Combined with the qualified Core 2.15.10 correction and source/database controls already linked above, this completes the reported lost-wake-up fix. Further PHP Server releases remain stopped. #947 remains separate for the native Nexus/host-query work.

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

    bugSomething isn't workingkind:defectA public product behavior is incorrectpriority:P1High-priority product or release risk

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions