Skip to content

Defer worker recycling to end of unit to preserve scope fixture teardown#106

Merged
thejchap merged 1 commit into
recycle-workers-on-test-countfrom
claude/address-pr-comments-PcQet
May 9, 2026
Merged

Defer worker recycling to end of unit to preserve scope fixture teardown#106
thejchap merged 1 commit into
recycle-workers-on-test-countfrom
claude/address-pr-comments-PcQet

Conversation

@thejchap
Copy link
Copy Markdown
Owner

@thejchap thejchap commented May 9, 2026

Summary

This change moves worker process recycling from the end of individual tests to the end of each work unit, ensuring that per="scope" fixture teardown is not skipped when a worker reaches the recycling threshold.

Key Changes

  • Moved recycling logic: Relocated the worker recycling check from run_single_test() to handle_unit(), placing it after finalize_hooks() completes
  • Preserves fixture lifecycle: By deferring recycling until the end of a unit, scope-level fixtures now complete their teardown (yield-after) before the process is recycled
  • Updated test structure: Modified worker_recycles_after_max_tests to submit one test per unit instead of batching tests, allowing the recycling check to fire as soon as the threshold is crossed
  • Added regression test: Introduced recycle_does_not_skip_scope_fixture_teardown to verify that scope fixture setup and teardown counts remain balanced (1:1) even when recycling occurs mid-unit

Implementation Details

The recycling logic checks if a worker process should be recycled (after MAX_TESTS_PER_WORKER tests) and gracefully shuts it down. Previously, this happened immediately after each test, which could drop the process before finalize_hooks() ran, leaving scope fixtures without their teardown calls. The new placement ensures the complete unit lifecycle (including all fixture teardowns) completes before recycling occurs. The next unit assigned to the worker will trigger ensure_worker() to spawn a fresh process and replay cached hooks, following the same path as crash recovery.

https://claude.ai/code/session_0143AyVfzSvwh3SCUbZxRUJ3

Recycling inside `run_single_test` could fire mid-unit, dropping the
live process before `handle_unit`'s `finalize_hooks` loop ran — and
that loop is gated on `state.process.as_mut()`, so per="scope" fixture
teardown was silently skipped (or run on a fresh worker's freshly
re-imported fixtures, double-counting setup). Move the recycle check to
after `finalize_hooks` in `handle_unit`.

Adjusts the existing recycle test to submit one unit per test (so the
end-of-unit check fires at the threshold) and adds a coverage test
that crosses the threshold inside a single unit with a per="scope"
fixture, asserting setup and teardown each run exactly once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thejchap thejchap merged commit c5311a1 into recycle-workers-on-test-count May 9, 2026
@thejchap thejchap deleted the claude/address-pr-comments-PcQet branch May 9, 2026 05:11
thejchap added a commit that referenced this pull request May 13, 2026
Recycling inside `run_single_test` could fire mid-unit, dropping the
live process before `handle_unit`'s `finalize_hooks` loop ran — and
that loop is gated on `state.process.as_mut()`, so per="scope" fixture
teardown was silently skipped (or run on a fresh worker's freshly
re-imported fixtures, double-counting setup). Move the recycle check to
after `finalize_hooks` in `handle_unit`.

Adjusts the existing recycle test to submit one unit per test (so the
end-of-unit check fires at the threshold) and adds a coverage test
that crosses the threshold inside a single unit with a per="scope"
fixture, asserting setup and teardown each run exactly once.

Co-authored-by: Claude <noreply@anthropic.com>
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