Backend-aware `fail_after` in pub/sub test
Mirror `060f7d24`'s pattern (backend-aware timeout in `maybe_expect_raises`) for `test_dynamic_pub_sub`'s hard `trio.fail_after` cap. Fork-based backends pay per-spawn fork+IPC-handshake cost which stacks over `cpus - 1` sequential `n.run_in_actor()` calls; empirically 12s flakes on `main_thread_forkserver` under UDS cross-pytest contention (#451 / #452). Defaults: - `main_thread_forkserver` → 30s - everything else → 12s (unchanged) Hoist the timeout-pick out of the `main()` closure so the dispatch happens once in the trio task rather than re-evaluating per spawn. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-codesubint_forkserver_backend
parent
060f7d24c4
commit
383b0fdd75
|
|
@ -157,17 +157,26 @@ def test_dynamic_pub_sub(
|
||||||
from multiprocessing import cpu_count
|
from multiprocessing import cpu_count
|
||||||
cpus = cpu_count()
|
cpus = cpu_count()
|
||||||
|
|
||||||
|
# Hard safety cap via trio's own cancellation — see the
|
||||||
|
# module-level NOTE on why we avoid `pytest-timeout` for
|
||||||
|
# this test. Picked backend-aware: under `trio` backend
|
||||||
|
# spawn is cheap (~1s for `cpus` actors) but fork-based
|
||||||
|
# backends pay a per-spawn cost (forkserver round-trip +
|
||||||
|
# IPC peer-handshake) that can stack up over `cpus - 1`
|
||||||
|
# sequential `n.run_in_actor()` calls — especially on UDS
|
||||||
|
# under cross-pytest contention (#451 / #452). Empirically
|
||||||
|
# 12s flakes on `main_thread_forkserver`; 30s gives
|
||||||
|
# plenty of headroom while still failing-loud on a real
|
||||||
|
# hang.
|
||||||
|
from tractor.spawn import _spawn as _spawn_mod
|
||||||
|
fail_after_s: int = (
|
||||||
|
30
|
||||||
|
if _spawn_mod._spawn_method == 'main_thread_forkserver'
|
||||||
|
else 12
|
||||||
|
)
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
# Hard safety cap via trio's own cancellation — see
|
with trio.fail_after(fail_after_s):
|
||||||
# the module-level NOTE on why we avoid `pytest-timeout`
|
|
||||||
# for this test. Total expected runtime: ~1s spawn + 3s
|
|
||||||
# sleep + ~1-2s cancel cascade ≈ 5-6s. 12s gives plenty
|
|
||||||
# of headroom; if exceeded, trio raises `TooSlowError`
|
|
||||||
# which the outer `try` block treats as a hang report
|
|
||||||
# (or, if `expect_cancel_exc is trio.TooSlowError`, as
|
|
||||||
# the test passing — either way, no global state
|
|
||||||
# corruption).
|
|
||||||
with trio.fail_after(12):
|
|
||||||
async with tractor.open_nursery(
|
async with tractor.open_nursery(
|
||||||
registry_addrs=[reg_addr],
|
registry_addrs=[reg_addr],
|
||||||
debug_mode=debug_mode,
|
debug_mode=debug_mode,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue