Skip to content

Expose sticky replay metadata in workflow polls - #313

Merged
rmcdaniel merged 3 commits into
mainfrom
fix/sticky-poll-metadata
Oct 8, 2026
Merged

rmcdaniel merged 3 commits into
mainfrom
fix/sticky-poll-metadata

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Addresses #312. Required by durable-workflow/.github#124 and
durable-workflow/sdk-python#102.

Project the bridge's authoritative sticky identity, expiry and replay mode into
the shared workflow poll payload. Preserve full replay for PHP SDKs before
2.2.0, whose sticky fallback rejects the valid StartAccepted history prefix.
Existing routing, lease and history semantics are unchanged. No codec, type,
framing or payload acceptance changes.

The published Server 2.5.9 reproducer completes a 1,200-side-effect workflow,
but its HTTP responses omit replay modes even when the durable leased task is
sticky_hit_expected. Python cannot safely use its warm history cache.

Verification

  • Regression fails against the original main poller because HTTP tasks omit
    the replay mode.
  • Candidate passes 126 affected PHP tests with 1,893 assertions, including
    cold, paginated warm, identical poll request retry and expired-affinity modes
    across legacy/current PHP and Python profiles.
  • The unchanged published PHP 2.1.5 consumer reproduces the original failure.
    With the compatibility fix it recovers that original run with the complete
    StartAccepted/WorkflowStarted prefix and exactly one activity/workflow
    completion. Two fresh standard workflows pass with the same locked SDK.
  • Python's real Server scenarios pass with the candidate poller overlaid on
    the exact published 2.5.9 image. They verify skipping a retained middle page,
    entry eviction, oversized history and replacement cold replay.
  • OpenAPI document revision 49 describes the existing metadata. The worker
    protocol version and payload codecs are unchanged.
  • Prepare Server 2.5.10 and chart 0.1.147 through the source release generator.
    The lockfile package graph is unchanged.

Pending final normal repository gates, review and exact published-image
verification. Keep #312 open until that verification succeeds.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 8, 2026 07:17
@rmcdaniel

Copy link
Copy Markdown
Member Author

Reviewed candidate b2a17ad16b2735b2ed546d5059a7f5e55c788c54 against
d97727113cef0d92228627eecb47988b0955aad9.

The implementation projects three existing affinity fields through the common
workflow poll payload builder. It preserves the current lease, task attempt,
history and routing policy. Cold tasks expose null identity/expiry and
cold_replay. Warm and expired-affinity modes come from the authoritative
bridge task. Identical poll request retries preserve the same task and mode.

The regression fails with the original poller and passes with the candidate.
The affected suites pass 121 tests and 1,767 assertions. Five real Python
scenarios pass against the candidate poller over the published 2.5.9 image:
paged warm reuse, entry eviction, oversized-history rejection, replacement
and a different build's refusal followed by recovery on the original build.
The 1,200-side-effect case downloads one tail page instead of both continuation
pages, and returns the expected result. The complete example reports two hits
and one miss.

OpenAPI revision49 adds optional nullable fields already described by the
affinity contract. It leaves payload codecs, worker protocol versions and
older workers' request shapes intact. The release generator changes deployment
references to Server2.5.10/chart0.1.147 without changing locked packages.

Safe rollback is the previous Server image. New workers then use full cold
history as before. No database migration or Cloud rollout is included.

The final normal perf smoke remains pending. Merge after it passes, publish
the exact reviewed source, then verify that published digest with Python before
closing #312. Python SDK #102 remains a draft until that dependency is delivered.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The first normal perf smoke caught a real compatibility regression in the
candidate, so merge remains pending.

The fixture uses published PHP SDK 2.1.5. Its sticky miss validator requires
WorkflowStarted as the first event, rejecting valid StartAccepted histories.
Exposing a warm replay hint activates that older fallback. This was confirmed
with the exact published SDK against the candidate Server poller.

The follow-up retains a null replay hint for registered PHP SDKs before 2.2.0.
They receive the original complete paginated history, identity and leases,
preserving their full replay behavior. Other capable worker profiles receive
the authoritative hint. PHP 2.2.0 introduced accepted-prefix support.

The 126 affected tests pass with 1,893 assertions. The real PHP 2.1.5 worker
recovers the original timed-out run with its original workflow/run IDs, intact
StartAccepted prefix, and exactly one activity and workflow completion. Two
fresh standard workflows also pass. The fixture's SDK pin is unchanged.

Rerun the normal source gates for the corrected candidate before merging.
Then qualify the published image with both legacy PHP and the new Python
consumer before closing #312.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Reviewed corrected candidate cc43a1e against
d977271.

The common poll projection exposes authoritative affinity metadata. The final
response preserves legacy PHP full replay by suppressing only its replay hint,
using the registered SDK identity. Routing, lease fencing, pagination and
StartAccepted history remain intact. PHP 2.2.0 and Python retain the new hints.

The 126 affected tests pass (1,893 assertions). The unchanged published PHP
2.1.5 consumer reproduces the original regression, then recovers its original
run and passes fresh workflows with the corrected Server. Seven Python cases
pass against the candidate overlay, including paged warm reuse, capacity/byte
limits, expiry, build refusal and a real SIGKILL with same-ID cold replacement.

All normal gates now pass, including the previously failing standard-workflow
canary in Server Perf
and the complete feature suite.
Rolling MySQL/Postgres, replay/query and Helm qualification also pass.

Publish Server 2.5.10 and chart 0.1.147 from the merged exact tree. Rollback is
the previous published image. Keep #312 open for published-image consumer
verification. No Cloud deployment is included.

@rmcdaniel
rmcdaniel merged commit fe09fe4 into main Oct 8, 2026
15 checks passed
@rmcdaniel
rmcdaniel deleted the fix/sticky-poll-metadata branch October 8, 2026 07:52
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