Files
buzz/crates
Meli 9d139889d0 fix(relay): never auto-end a huddle on drain; hold empty rooms 20s
A relay drain (SIGTERM or owner-drain) cancelled every local owner client
at once, so the last teardown emptied the room and took the archive +
48103 path: every pod restart ended every huddle it owned. The same path
also ended a huddle the instant its last client blipped, so a reconnect
found the channel archived.

The leave path now distinguishes a drain-driven teardown (the owner
draining token fired, or `shutting_down` / `owners.is_draining()` is set,
covering single-pod mode where there is no mesh token) and only releases
the lease and drops the empty room, leaving the channel alive for
rejoiners to re-acquire through Redis.

Ordinary last-leaver departures no longer end the room atomically.
`remove_peer_and_check_idle` captures an `IdleGeneration` (the admission
count) under the guard lock; a spawned task waits `ROOM_EMPTY_GRACE` and
calls `end_if_idle`, which sets `ended` only if the room is still empty
and no admission happened in between. A rejoin during the window fences
the stale observation even if the rejoiner has already left again, and
two leavers who both observed empty cannot both archive. Owner-loss or a
drain that begins mid-window aborts the end; owner-loss wins a tie with
the timer.

The fence only holds if the rejoiner lands on the same `Room`. A
pre-last leaver's `cleanup_if_empty` (or a failed pre-admission join)
could run after the last leaver's idle observation and evict the empty
room from the manager; the rejoiner would then get a fresh `Room` and the
stale grace task would archive underneath it. The idle observation now
sets `idle_hold` on the room and `cleanup_if_empty` refuses to evict
while it is set. The hold survives `end_if_idle` so the room stays
registered while `archive_channel` is in flight — a joiner in that gap
meets `ended` on the same room instead of admitting into a fresh one
whose pre-join DB check raced the archive. The hold clears on admission
or via the fenced `release_idle_hold`, called after the archive resolves
(success or rollback) and on the drain/abort paths that abandon the
window.

Tests: room idle generation (last-leaver-only, end-once, rejoin fences
stale), manager eviction (concurrent-leaver ordering pins the room and
the rejoiner fences the stale end; released hold permits eviction, stale
release does not; ended room stays pinned and refuses joiners until the
archive resolves; failed archive reopens and releases), and paused-time
grace outcomes (holds through window,
rejoin, no-rejoin ends, owner-loss aborts, mid-window drain aborts).

Co-authored-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
Signed-off-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
2026-08-22 20:14:15 -04:00
..