CompositeLoom
A Loom that weaves one logical session from several constituent Looms ("plies"). The union of plies covers the session's peer set; the list order is a send-preference hint (most-preferred first).
The ply set may change while the session is live: construct with a StateFlow of the desired set and push a new list to attach or detach plies. Each emission is reconciled against the current live set — new entries are woven in, removed entries are detached. The list constructor is the degenerate case of a never-changing flow.
Already carries the universal knobs it can honour (#1430), and deliberately omits the two it cannot. dispatcher and policy below are the canonical parameters, under the canonical names and defaults. The other two are absent on purpose:
selfId— a composite has no identity to give. The bonded seam's Seam.selfId is derived from the plies that came up (CompositeSeam.mintCompositeIdjoins their ids), so a loom-level identity would have to either overwrite that derivation — losing the record of which transports this session is actually made of — or be accepted and dropped.weaveTimeout— weave is a loop overloom.weave(rendezvous), so its duration is already the sum of each ply's own rendezvous. A clock here would either duplicate a bound the ply enforces or silently pre-empt one, and because the weave is all-or-nothing the caller could not tell which ply the deadline cut short. A consumer that needs a deadline puts it on the ply that owns the slow rendezvous, where the failure is attributable.
Parameters
The desired ply set; emit a new value to reconcile (attach/detach).
Forwarded to each CompositeSeam as the scope for its internal coroutines (scheduling only — the woven seam's thread-safety is via a lock + atomics, so it is correct under a multi-threaded dispatcher). Production default (Dispatchers.Default); tests inject a dispatcher derived from the test scheduler.
Governs the inbound us.tractat.kuilt.core.Spool's capacity and overflow behaviour for each woven CompositeSeam. Defaults to DeliveryPolicy.Reliable (bounded, backpressured, lossless).
Raised whenever one ply fails inside a live session — a constituent Loom's capability()/weave() or a ply Seam's close() threw while reconciling, or a peer sent an inbound frame the ply could not process. The composite absorbs the failure and keeps going: the other plies still reconcile, a failed attach is retried on the next plies emission, and a ply whose inbound frame failed drops that frame and keeps delivering. kuilt-core is logger-free, so this is how that surfaces to a consumer's own logger. Best-effort and non-suspending; defaults to a silent absorb. See PlyReconcileException.
Constructors
Static convenience: a fixed ply set that never changes after weave().
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.
Weave every ply in the current desired set and bond them into one Seam.