Files
hermes-agent/tests/hermes_cli/test_retirement_atomicity.py
brooklyn! 98745df3b9 fix(serve): hold work admission through cooperative retirement
Fence accepted RPCs, side agents, continuations, delegation and cron before issuing process-bound retirement permits.

Co-authored-by: chelsealong <chelsealong@126.com>
Co-authored-by: Mark Sheppard <mark@orchardstreetpress.com>
2026-09-17 00:34:50 -05:00

51 lines
1.8 KiB
Python

"""Freeze admission before consulting ledgers, without holding a lock across their locks."""
from concurrent.futures import ThreadPoolExecutor
import threading
def test_prepare_freezes_admission_without_blocking_other_work_locks(monkeypatch):
from hermes_cli.backend_retirement import RetirementFence
from hermes_cli import web_server_idle_proof
fence = RetirementFence()
probing, release, attempted = (threading.Event() for _ in range(3))
def probe():
probing.set()
assert release.wait(10)
return {"idle": None}
def admit():
with fence.work() as admitted:
attempted.set()
return admitted
monkeypatch.setattr(web_server_idle_proof, "idle_proof", probe)
with ThreadPoolExecutor(max_workers=2) as pool:
preparing = pool.submit(fence.prepare)
try:
assert probing.wait(10)
arriving = pool.submit(admit)
assert attempted.wait(3), "admission must not wait on a ledger lock held by its own caller"
assert arriving.result(10) is False
finally:
release.set()
assert preparing.result(10) == {"ok": False, "idle": None}
with fence.work() as admitted:
assert admitted # unreadable/busy probe did not leave a fence behind
def test_probe_failure_refuses_the_permit_without_wedging_admission(monkeypatch):
from hermes_cli.backend_retirement import RetirementFence
from hermes_cli import web_server_idle_proof
def broken_probe():
raise OSError("ledger unavailable")
fence = RetirementFence()
monkeypatch.setattr(web_server_idle_proof, "idle_proof", broken_probe)
assert fence.prepare() == {"ok": False, "idle": None}
with fence.work() as admitted:
assert admitted