SeamRoomFactory
Loom-backed implementation of RoomFactory.
Each call to host or join weaves a new Seam via loom, wraps it in a SeamRoom, and drives the admit/identify handshake:
Host side: passively collects AdmitMessage.Hello from new peers and replies with AdmitMessage.Welcome, adding the peer to the roster and broadcasting the welcome to all other admitted members.
Joiner side: immediately sends AdmitMessage.Hello via broadcast and waits for the AdmitMessage.Welcome that confirms admission.
scope is used to launch the per-Room admit loop coroutines. Callers should use a scope whose lifetime matches the room's intended lifetime (e.g. backgroundScope in tests, a structured session scope in production).
SeamRoom's internal membership state is guarded by a reentrant lock and is safe under any dispatcher, including multi-threaded ones such as Dispatchers.Default. Suspend calls (sends, broadcasts) are always performed outside the lock.
clock is required (not defaulted) so callers must make an explicit choice: use SeamRoomFactory.systemClock for production wall-clock time or supply a virtual clock in tests. An accidental epoch-zero default would ship wrong timestamps silently.
heartbeatConfig controls partition-detection timing.
admitTimeout bounds the joiner's admit handshake: if no AdmitMessage.Welcome arrives within this window after the joiner's Hello, the room surfaces a terminal MembershipEvent.AdmissionFailed with AdmissionFailure.TimedOut instead of waiting forever (#1178). Hosts ignore it.
See also
for the production convenience constructor.
Constructors
Functions
Symmetric lobby entry both peers call identically: weave the mesh via us.tractat.kuilt.core.Rendezvous.New (a constant session name), then return an ElectionLobby over the woven seam. Every peer elects the same host (min(peers)); on Start the elected host runs the freeze round and each peer adopts a Room once (#1439).