Replace test-count recycling with resource-based worker limits#108
Merged
thejchap merged 1 commit intoMay 11, 2026
Merged
Conversation
Replaces the hardcoded `MAX_TESTS_PER_WORKER = 128` cap with
self-reported resource snapshots: every `run_test`/`run_doctest`
response carries a `WorkerHealthWire { rss_bytes, open_fds }` that the
runner consults at unit boundaries alongside a wall-clock age check.
Recycle decisions now name the tripped signal via a `RecycleReason`
enum, so debug logs can attribute drops to memory pressure vs FD
exhaustion vs slow drift.
Soft ceilings live on `WorkerLimits` (1 GiB RSS / 200 FDs / 10 min by
default, all `Option<u64>` so platforms without `/proc/self/fd` or
`resource` simply skip that signal). Tests use the new
`WorkerPool::with_python_path_and_limits` constructor with tiny caps
(or `WorkerLimits::unlimited`) to exercise recycle behaviour
deterministically; production call sites in `tryke`, `tryke_server`,
and `tryke_dev` are unchanged because `with_python_path` defaults to
`WorkerLimits::default()`.
Test coverage: end-to-end age-based recycle test (replaces the
test-count one); existing scope-fixture-teardown test now triggers via
age cap; new unit tests for `evaluate_recycle` priority order and
no-signal/no-cap fallbacks.
https://claude.ai/code/session_01PMbxzSuASTEYbDFEu4SQqy
thejchap
added a commit
that referenced
this pull request
May 13, 2026
Replaces the hardcoded `MAX_TESTS_PER_WORKER = 128` cap with
self-reported resource snapshots: every `run_test`/`run_doctest`
response carries a `WorkerHealthWire { rss_bytes, open_fds }` that the
runner consults at unit boundaries alongside a wall-clock age check.
Recycle decisions now name the tripped signal via a `RecycleReason`
enum, so debug logs can attribute drops to memory pressure vs FD
exhaustion vs slow drift.
Soft ceilings live on `WorkerLimits` (1 GiB RSS / 200 FDs / 10 min by
default, all `Option<u64>` so platforms without `/proc/self/fd` or
`resource` simply skip that signal). Tests use the new
`WorkerPool::with_python_path_and_limits` constructor with tiny caps
(or `WorkerLimits::unlimited`) to exercise recycle behaviour
deterministically; production call sites in `tryke`, `tryke_server`,
and `tryke_dev` are unchanged because `with_python_path` defaults to
`WorkerLimits::default()`.
Test coverage: end-to-end age-based recycle test (replaces the
test-count one); existing scope-fixture-teardown test now triggers via
age cap; new unit tests for `evaluate_recycle` priority order and
no-signal/no-cap fallbacks.
https://claude.ai/code/session_01PMbxzSuASTEYbDFEu4SQqy
Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replace the fixed
MAX_TESTS_PER_WORKERconstant with a flexible, resource-aware worker recycling system that monitors memory usage, open file descriptors, and wall-clock age.Summary
Worker processes are now recycled based on soft resource ceilings rather than a hard test count. This allows the runner to respond to actual resource pressure (memory leaks, FD accumulation) while remaining deterministic and testable.
Key Changes
New resource monitoring types (
WorkerHealth,WorkerLimits,RecycleReason):WorkerHealth: Captures worker self-reported RSS bytes and open FD countWorkerLimits: Configurable soft ceilings (default: 1 GiB RSS, 200 FDs, 10 min age)RecycleReason: Enum indicating which limit triggered recycling, with human-readableDisplayimpl for debug logsPure recycle-decision logic (
evaluate_recyclefunction):WorkerProcessfor unit testabilityNonelimits (opt-out) and missing readings (platform unavailability)Worker-side health reporting (Python):
_measure_rss_bytes()and_measure_open_fds()functions usingresourcemodule and/proc//devfilesystem_measure_health()snapshot attached to everyrun_test/run_doctestresponseNonefor unavailable signals rather than guessingProtocol updates:
WorkerHealthWirestruct for wire formatRunTestResponseWirewrapper combining health snapshot with test resulthealthfieldPool API expansion:
WorkerPool::with_python_path_and_limits()for tests to set custom limitsWorkerSpawnCtxstruct bundles spawn-time parameters to reduce signature bloatTest updates:
worker_recycles_after_max_tests→worker_recycles_when_age_exceeds_limit: Uses tinymax_agecap and sleep to drive deterministic recyclingrecycle_does_not_skip_scope_fixture_teardown: Simplified to use age-based recycling within a single unitNotable Implementation Details
per="scope"fixture teardown runs before process deathWorkerLimits::unlimited()helper disables all caps for tests exercising one signal in isolationhttps://claude.ai/code/session_01PMbxzSuASTEYbDFEu4SQqy