Skip to content

Fix activity pause test races - #1831

Draft
DABH wants to merge 1 commit into
mainfrom
flake/activity-pause-races
Draft

DABH wants to merge 1 commit into
mainfrom
flake/activity-pause-races

Conversation

@DABH

@DABH DABH commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

What was changed

The unpause helper accepts an activity that has already completed after a successful unpause RPC. Pause-specific activities keep their 10s start-to-close deadlines and heartbeat delivery, but drop the unrelated 1–2s heartbeat failure deadlines. The cancellation-details worker now caps heartbeat throttling at 300ms; pause/unpause already used that cap.

The shared pending-activity wait defaults to 10s, covering paths that still used 5s. The first pause/unpause readiness call already explicitly allows 10s on current main. The external cancellation test now requires the heartbeat to raise AsyncActivityCancelledError with paused=True.

Why

An unpaused retry can finish before the next describe response. Short heartbeat failure deadlines can also time an activity out before the pause request reaches it. These tests verify pause behavior, so heartbeat delivery should stay prompt without introducing a competing heartbeat timeout. The final workflow-result assertions still verify successful completion.

Testing

Rebased on main 76875b8; Python 3.14.3, SDK 1.34.0, freshly built matching Core 472f94e, pinned Server 1.32.0-162.0.

  • 30/30 normal repetitions across the three affected tests.
  • Controlled 1.7s post-unpause observation delay, 6s cold workflow-poller delay, and 2.6s heartbeat blackout: all pass. The same cases failed on unpatched current main during review.
  • Histories retain real pause cancellations and successful activity retries.
  • poe lint passes, including all three type checkers.

CI run 38442762780 is green on commit 31e21203. Its first macOS 3.10 attempt timed out in the unchanged test_alternate_async_loop_ordering; rerunning that one job passed without a source change. Side-by-side runs of that unchanged test also passed on main and this patch under Python 3.10.20 and 3.14.3.

These bounded reproductions verify the timing mechanisms; they do not measure the current CI flake rate.

@DABH DABH added the skip-changelog PR changes do not require changelog updates label Sep 10, 2026
@DABH
DABH requested a balanced review from Copilot September 10, 2026 06:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused test changes consistently address the documented races without altering production behavior.

Pull request overview

Stabilizes activity pause tests by reducing timing races around heartbeats, retries, and cold starts.

Changes:

  • Uses fixed 300 ms heartbeat throttling without short heartbeat timeouts.
  • Accepts completed activities as successfully unpaused.
  • Strengthens cancellation assertions and extends pending-activity polling to 10 seconds.
File summaries
File Description
tests/worker/test_workflow.py Adjusts heartbeat timing and cancellation assertions.
tests/helpers/__init__.py Makes pending and unpause assertions race-resistant.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@DABH DABH left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend keeping this PR and rebasing it onto current main. The exact two-file patch applies cleanly to 76875b8, and I found no actionable P1/P2 regression.

Using Python 3.14.3, a freshly built matching Core 472f94e bridge, and the pinned Server 1.32.0-162.0:

Controlled case Current main With this patch
Observe pending activity 1.7s after successful unpause Fails Passes
Delay the first workflow poll by 6s Fails Passes
Suppress heartbeats for 2.6s and delay pause observation Activity times out before pause; test fails Passes
Make the external heartbeat return without cancellation Incorrectly passes Correctly fails

Normal repetitions passed 30/30 before and 30/30 after; no natural flake occurred in that sample. The controlled cases demonstrate the timing mechanisms rather than an empirical CI failure rate.

The implementation preserves the behavior under test. Histories show real paused=True cancellation delivery with no heartbeat failure deadline; both unpaused activities complete on attempt 2. Disabling heartbeats entirely still fails the patched test. Removing the short heartbeat failure deadlines while keeping prompt heartbeat delivery is appropriate for testing pause behavior.

Please update the rationale for drift: current main already gives the first pause/unpause readiness poll 10s, although the helper default and other paths remain 5s. Also, pause/unpause already capped heartbeat throttling at 300ms; the new throttle setting is needed by the cancellation-details worker. The heartbeat fault produced an activity timeout followed by "workflow execution already completed", rather than the exact pending-activity error quoted in the description.

@DABH
DABH force-pushed the flake/activity-pause-races branch from af9f09d to a77a719 Compare October 13, 2026 17:54
Accept an activity that has already finished after a successful unpause RPC.
The tests still await and verify the workflow result.

Remove the pause-specific workflows' short heartbeat failure deadlines while
keeping prompt heartbeat delivery. Add the 300ms throttle to the cancellation-
details worker; the pause/unpause worker already had that cap.

Raise the shared pending-activity wait to 10s for paths that still use its
default. The first pause/unpause readiness call already explicitly allows 10s.

Require the external heartbeat to raise the expected paused cancellation.
@DABH
DABH force-pushed the flake/activity-pause-races branch from a77a719 to 31e2120 Compare October 13, 2026 17:56
@DABH

DABH commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

CI is now green on 31e21203: CI run.

The macOS Python 3.10 timeout was in test_alternate_async_loop_ordering, whose implementation is unchanged from current main. It did not reproduce in paired main/PR checks on Python 3.10 and 3.14; one rerun of the failing job passed without source changes. The activity-pause changes and their assertions remain as implemented.

This branch has not been deployed

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

Labels

skip-changelog PR changes do not require changelog updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants