tieredSeam

fun tieredSeam(local: Seam, peer: Seam, scope: CoroutineScope, policy: DeliveryPolicy = DeliveryPolicy.Reliable): Seam

Bond a local-tier and a peer-tier Seam — two views of the same node onto two disjoint peer sets — into one Seam whose roster is the union of both.

The motivating case (game-overlay slice 6) is a federated per-game seam: the local tier is a room's RoomHubSeam (the members physically connected to this server) and the peer tier is NamedMux(coreMesh).channel(gameId) (the other servers, one hop across the core mesh). A per-game broadcast must reach the local room and cross to the other servers — two transports, two rosters — so this presents them as one seam. The primitive itself knows nothing about rooms, games, or clusters: it is a generic seam composition, beside us.tractat.kuilt.core.composite.CompositeSeam / RoomHubSeam / NamedMux.

Contract

  • peers is the live union local.peers ∪ peer.peers, recomputed whenever either tier's roster changes. The two rosters are assumed disjoint; if they overlap, the union simply dedups by PeerId (a shared id resolves to one entry, and sendTo routes it to the local tier — see below).

  • incoming is the merge of both tiers' incoming. This seam becomes the sole collector of both underlying seams' incoming (started eagerly on scope) and its own incoming is itself single-collection (collect once, per the ADR-034 contract). Callers must not collect either underlying seam's incoming elsewhere — exactly as NamedMux and RoomHubSeam own the collection of what they wrap.

  • broadcast tees to BOTH tiers (the frame reaches the local room and crosses to the other servers). Each side is best-effort and independent: a failure on one tier never prevents the other from being attempted.

  • sendTo routes to whichever tier owns the addressed peer — peer ∈ local.peerslocal.sendTo, else peer ∈ peer.peerspeer.sendTo, else the peer is absent from the union and PeerNotConnected is thrown, as Seam.sendTo requires of every fabric (#1935). It never fans to both: unicast stays single-addressee across the union, preserving the ADR-005 single-addressee leak boundary. (A shared/overlapping id resolves to the local tier, since it is checked first.)

  • selfId — both tiers are the same node, so local.selfId must equal peer.selfId; construction throws IllegalArgumentException otherwise.

  • state is the composed lifecycle: Woven while either tier is Woven (the surviving tier carries), Weaving while forming, and Tornterminal, latched — once both tiers are Torn or close is called. Both-tiers-torn is genuinely terminal here (not a revivable rollup) because this union's incoming is a one-shot merge that completes permanently when both tiers' incoming complete — so reporting a recoverable Weaving would contradict a terminally-completed incoming. This differs from us.tractat.kuilt.core.composite.CompositeSeam, whose persistent spool survives ply churn, so its all-plies-torn rollup is recoverable Weaving (#1367). close closes both tiers.

Thread safety

Correct under a multi-threaded dispatcher, by real primitives — never single-thread confinement. state runs through a SeamStateGate: the combine state pump publishes via update() (a no-op once torn) and close latches Torn via tear(), so no in-flight pump write can overwrite the terminal state and tear()'s single-shot return subsumes the old close latch. peers is written from a single combine collector, but that write races collapseRoster, so both are guarded by a small reentrantLock with the collapse marker folded into the same critical section — a post-collapse peers emission cannot resurrect the roster. The marker rather than a read of state is load-bearing: Seam.peers requires the collapse to be published before the Torn latch, so mid-close there is an instant at which the roster is collapsed and state is not yet terminal. incoming flows through a bounded Spool.

Parameters

scope

required parent scope for the union/incoming pumps — no real-dispatcher default (a default would silently decouple the pumps from a test's virtual clock). The internal coroutines run on a child of this scope so close cancels them without tearing the caller's scope.

policy

governs the merged inbound Spool's capacity/overflow. Defaults to DeliveryPolicy.Reliable (bounded, backpressured, lossless).