MuxServerLoom
A server-side Loom that provides structural per-room isolation over a shared ConnectionSource.
Each accepted Connection is handshaked into a 2-peer Seam and read exactly once; inbound frames are demultiplexed by channel name (the NamedFrame wire header) and pushed into the matching RoomHubSeam. host for a given room name returns that RoomHubSeam — a server-centred star Seam that forwards broadcasts only to connections admitted to that room. A connection joins a room when its first frame arrives on that room's channel AND authorizer grants admission. A non-member is never in the fanout list — isolation is by construction, not by runtime guard.
Why single-collection-and-demux
Routing per-room registration through a NamedMux channel view (a replay-0 shareIn plus a per-view pipe) makes registration depend on subscription timing — a frame can arrive before the room's collector subscribes and be lost, leaving a peer permanently unregistered. Reading each connection's seam once and pushing demuxed frames into a bounded Spool inside each room removes that race: the buffered spool retains a frame delivered before the room's consumer subscribes, so registration and fanout are deterministic under virtual time.
Usage
val serverLoom = MuxServerLoom(
source = source,
scope = scope,
selfId = PeerId("server"),
authorizer = RoomAuthorizer { peer, tag -> sessionStore.isAdmitted(peer, tag) },
)
val room7 = serverLoom.host(Pattern("table-7"))
val room9 = serverLoom.host(Pattern("table-9"))Reconnect / resume (server side)
Membership is keyed by PeerId, not by the underlying connection. When a connection with a previously-seen PeerId is accepted (a reconnect over a fresh transport with the same identity), its demuxed frames re-register it into whatever room its tags name. Because RoomHubSeam keys its registration map by PeerId and compares the outbound handle by identity, the returning connection lands back in exactly the rooms it re-announces, and the dropped connection's later teardown does not evict the resumed membership. Client-side resume (re-emitting tags after a drop) lives in a separate concern; this Loom handles only the server-side re-association.
join throws UnsupportedOperationException — this is a server-only Loom.
Lifecycle
A ScopedCloseable: the accept loop and every per-connection read/watch pump run in an owned child scope whose job is a child of scope's job. Cancelling scope therefore stops every pump, and close tears the loom down explicitly — it halts the accept loop, cancels all per-connection pumps, and (via each read loop's teardown) deregisters the connection from the rooms it joined. close is idempotent. It does not tear the hosted RoomHubSeams or the per-connection mesh seams: those have independent lifecycles owned by their consumers and by the source/connection provider respectively.
Thread safety
connRecords, rooms, and launchedJobs are guarded by lock. Suspend calls are always outside the lock.
Parameters
accept source for incoming client connections.
this server's own PeerId.
required authorization policy for per-room membership. Invoked on the first inbound frame per (connection, room) pair; a false return structurally excludes the connection from that room. Use RoomAuthorizer.AllowAll for open-access servers. Required (no default) per the "optional ≠ tuning" rule — absent it the gate would be silently disabled.
coroutine context for mesh-seam link loops. Defaults to the interceptor from scope so virtual-time tests share the test dispatcher automatically.
seeded Random for mesh-seam nonce generation.
ceiling on a single accepted connection's handshake+admit; a connection that connects but never completes its MeshHello handshake is abandoned and closed after this, so it can never wedge the accept loop. Each accepted connection is admitted concurrently in its own child coroutine (all shared state is lock-guarded), so a slow handshake never starves later connections either.
Constructors
Functions
Whether this fabric can be attempted now — the availability half of capability. Derived; do not override.
This fabric's role(s) and whether it can be attempted now. The single capability primitive — override this, not availability. Default: a roleless FabricAvailability.Available.
Establish a Seam according to rendezvous — either host a new session or join an existing one.