fix(issue-50): an injected record holds its session whatever its FIFO place; the ambient pane claim locks the caller's server (reviews 5a09a13f F-A, e8e471ff R1)
open_jobs reports a live pending record nobody signals on as `injected`: its producer registered and injected it without a waiter (create --onboard, a job sent by hand), so it holds the session like a running or admitted job, and a waiter of the same second with a lower job id, or one registered a moment earlier and still in its preflight, no longer passes it in the FIFO. The waiter signals on its own record before its first scan, so its record is never mistaken for one. lib_py.pane_lock resolves the shim's ambient target (no -L, HERDR_SESSION_NAME empty or `default`) to the server of the pane the caller runs in - HERDR_SESSION, else HERDR_SOCKET_PATH's layout, as lib.sh _herdr_caller_server reads them - so an ambient and a named call into one server claim under one lock; outside a pane it stays the default server's. Tests: u2h (the tie, the later-registered onboarding, the signalled control), u1/u4 labels, c10 forces the same-second registration, p1b, s2 (real herdr: held lock stops both call forms; mixed concurrent calls take distinct panes). Two FIFO fixtures now carry a waiter's signal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
d50610c1ab
commit
6c99fedf40
7 files changed
+168
-22
No files matched your search
@@ -55,6 +55,31 @@ def test_p1_the_lock_file_is_per_server_under_the_sessions_home(tmp_path):
|
||||
assert res.stdout.strip() == pane_lock.lock_path("t50-x", env), res.stderr
|
||||
|
||||
|
||||
# review e8e471ff R1: the ambient target (no -L, HERDR_SESSION_NAME empty or
|
||||
# `default`) is answered by the server of the pane the caller runs in - the
|
||||
# pane's HERDR_SESSION / HERDR_SOCKET_PATH say which - so that is the lock;
|
||||
# only outside a pane is it the default server's
|
||||
|
||||
def test_p1b_the_ambient_target_locks_the_callers_server(tmp_path):
|
||||
home = {"HOME": str(tmp_path)}
|
||||
sock = {"HERDR_SOCKET_PATH": str(tmp_path / ".config/herdr/sessions/t50-x/herdr.sock")}
|
||||
named = pane_lock.lock_path("t50-x", home)
|
||||
for ambient in ("", "default", None):
|
||||
assert pane_lock.lock_path(ambient, {**home, **sock}) == named, ambient
|
||||
assert pane_lock.lock_path(ambient, {**home, "HERDR_SESSION": "t50-x"}) == named, ambient
|
||||
assert pane_lock.lock_path(ambient, {**home, "HERDR_SESSION": "t50-x", # HERDR_SESSION first
|
||||
"HERDR_SOCKET_PATH": str(tmp_path / ".config/herdr/sessions/t50-y/herdr.sock")}) == named
|
||||
assert pane_lock.lock_path(ambient, {**home, "HERDR_SOCKET_PATH": str(tmp_path / ".config/herdr/herdr.sock")}) \
|
||||
== pane_lock.lock_path("default", home) == str(tmp_path / ".local/state/mam/pane-lock/default.lock")
|
||||
assert pane_lock.lock_path(ambient, {**home, "HERDR_SOCKET_PATH": "/elsewhere/herdr.sock"}).endswith("/default.lock")
|
||||
assert pane_lock.lock_path(ambient, home).endswith("/default.lock")
|
||||
assert pane_lock.lock_path("t50-y", {**home, **sock}) != named, "a named target is that server's, wherever it is called from"
|
||||
outside = {k: v for k, v in os.environ.items() if not k.startswith("HERDR_")} # this test may run in a pane
|
||||
res = subprocess.run([sys.executable, "-m", "lib_py.pane_lock", "path", "--session", ""], capture_output=True, text=True,
|
||||
env=dict(outside, PYTHONPATH=str(SKILLS), HOME=str(tmp_path), **sock), timeout=60)
|
||||
assert res.stdout.strip() == named, res.stderr
|
||||
|
||||
|
||||
def test_p2_a_free_lock_is_taken_at_once_and_a_held_one_times_out(tmp_path):
|
||||
lock = tmp_path / "s.lock"
|
||||
t0 = time.time()
|
||||
|
||||
Reference in new issue
Block a user