KtorMeshClientLoom
Client-side Loom that joins a hub-spoke mesh — the spoke counterpart of a us.tractat.kuilt.core.MuxServerLoom hub.
join opens a WebSocket to the WebSocketAdvertisement URL and returns a mesh spoke Seam: it exchanges the in-band mesh preamble (us.tractat.kuilt.core.fabric.MeshSeam's MeshHello) so both ends learn each other's PeerId over the wire. This is exactly what a MuxServerLoom hub requires — it handshakes every accepted connection as a mesh spoke — and it is why this loom exists: pointing a KtorClientLoom at a MuxServerLoom hub silently never completes admit (a KtorClientLoom returns a 2-peer WebSocketSeam with no in-band handshake, so the hub's preamble is never satisfied). Before this loom, every consumer hand-rolled the meshSeam(selfId, listOf(WebSocketConnection(session)), dispatcher) base itself.
Pairing: KtorMeshClientLoom ↔ us.tractat.kuilt.core.MuxServerLoom hub — hub-spoke mesh with a MeshHello preamble. Contrast KtorClientLoom ↔ KtorServerLoom/KtorRoomHost — a 2-peer relay with no in-band handshake.
PeerId discovery:
This spoke's own PeerId is fixed at construction as selfPeerId and appended as
?peer=<id>on every join (mirroring KtorClientLoom) and, redundantly, carried in the in-bandMeshHello.The remote hub's PeerId is learned from the
MeshHellopreamble it sends back — it does not come from WebSocketAdvertisement.serverPeerId (the mesh handshake is authoritative).
Stable identity across reconnects: supplying selfPeerId gives this loom a fixed fabric identity reused on every call to weave/join — required wherever a server derives a stable learner identity from the admitted PeerId. The default mints a fresh random identity per loom instance.
HttpClient lifecycle: the httpClient is not closed by this loom. Callers are responsible for closing it when all connections are done.
Parameters
Scheduler for the mesh spoke's per-link read loop; passed directly to peerMesh (which guards its own state with primitives — the dispatcher is scheduling-only, never a serialization crutch). Production default is Dispatchers.Default; tests inject a dispatcher derived from the test scheduler.
The fabric identity this loom presents on every join. Defaults to a random UUID minted once at construction; supply a deterministic value for stable identity across reconnects.
Source of the per-connection mesh nonce. Production defaults to Random.Default; tests pass a seeded Random so the dedup tiebreak is deterministic.
Delivery policy for the spoke seam's inbound spool. Defaults to DeliveryPolicy.Reliable.
See also
the 2-peer relay client (pairs with KtorServerLoom/KtorRoomHost).
the hub this spoke joins.
the composition this loom produces — a peer-mesh spoke that latches Torn when the hub drops its single link (honouring the incoming-completes-on-Torn contract).
Constructors
Functions
Establishes a mesh spoke Seam: