mirror of
https://github.com/block/buzz.git
synced 2026-11-02 15:31:27 +00:00
The read side elected nobody: with no writer, every instance read an absent lock and defaulted to leader, so a shared agent key produced duplicate responders. Add the writer half so one instance actually wins. The harness self-mints a process-unique election id (from_env_or_mint), acquires the lock on startup, re-attempts the claim on the existing 5s refresh tick (failover when a leader dies without releasing), and releases on graceful shutdown. acquire holds an exclusive flock across the read-decide-write window to close the TOCTOU race; a dead-pid lock is reclaimable, a live foreign lock is not. release empties the file rather than unlinking it to avoid racing a fresh claim onto a detached inode. Failover tolerates pid recycling: a crashed leader's pid may be reused by an unrelated live process, which a bare pid-liveness probe would mistake for the original leader and never take over, wedging the agent leaderless. A claim is takeable when its pid is dead OR its claimed_at is older than a staleness bound (2x the 5s refresh); a live leader rewrites claimed_at every tick, so only an abandoned claim ages out, without evicting an active leader. Writer is Unix-only (flock); non-Unix gets an always-leader no-op, mirroring the kill_process_group cfg fallback. NIP-LE amended to final state: claim is auto-on-launch plus explicit re-claim. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>