InMemoryLoom

class InMemoryLoom(policy: DeliveryPolicy = DeliveryPolicy.Reliable) : Loom

In-memory implementation of Loom for use in tests and integration harnesses. All Seam instances produced by the same factory instance share a single in-memory mesh.

One instance is exactly one flat mesh — hence one concurrently hosted room. A single InMemoryLoom has no notion of separate sessions: every seam it weaves (whether via host/Rendezvous.New or join/Rendezvous.Existing) joins the same peer set and receives every broadcast on it. So the correct shape is one host plus any number of joins — that is the whole mesh.

Hosting a second, concurrent room on one instance (a second Rendezvous.New while the first host seam is still live) is a misuse: the two "rooms" would silently cross-admit each other's members over the shared mesh rather than being isolated. To make that loud rather than silently corrupt, a second concurrent Rendezvous.New throws IllegalStateException. For multi-room tests, use one InMemoryLoom per room, or the InMemoryRoomFabric helper in :kuilt-test.

Re-hosting after the prior host tears is allowed. Once the hosting seam is closed/removed, a fresh Rendezvous.New is permitted again — this models a real fabric's re-host-after-drop and keeps client-side resume (MuxClientLoom re-weaves its base after a tear) and dynamic ply re-attach (CompositeLoom re-weaves a detached ply) working over the in-memory bedrock. The guard rejects two live hosts, never a sequential re-weave. Rendezvous.Existing (joiners) stays unlimited and never touches the guard.

Thread-safe, from two separate mechanisms — worth naming apart, because the Mutex is the factory's and does not reach inside a seam. The shared mesh state (the link registry, the peer roster, sequence assignment) is protected by that Mutex; a seam's own close-once latch is outside it and is atomic in its own right, since close is reachable concurrently from any dispatcher (#2328). Frame delivery is bounded and backpressured via one Spool per link, with overflow behaviour chosen by DeliveryPolicy.

The suspending deliver call happens outside the factory mutex — sequence numbers are assigned under the lock, then delivery is performed after releasing it, so a SUSPEND-policy backpressure suspension never holds the mutex.

Not a production transport — no discovery, no network, no serialization. Intended to be the test bedrock for :session-protocol and every layer above it.

Three of the four universal factory knobs are deliberately absent (#1430). The convention puts selfId, policy, weaveTimeout and dispatcher on a fabric factory only where the fabric honours them — an accepted-then-ignored argument is worse than an absent one — and here only policy survives that test:

  • selfId — one loom is one mesh with many seams, and the link registry is keyed by each seam's PeerId. A loom-level identity would hand every seam the same key, so a second weave would evict the first from the registry and peers would collapse to a single entry. The knob is not merely meaningless here, as it is on a one-seam-per-loom fabric; it is structurally incompatible with one-loom-many-seams. Identity is minted per seam by nextMeshPeerId instead, whose KDoc explains why it is a counter and not freshPeerId.

  • weaveTimeout — weave reaches no remote and never suspends on one: both branches take the mutex and hand back an already-live seam. There is no rendezvous for a clock to bound, so LoomDefaults.WEAVE_TIMEOUT has nothing to apply to.

  • dispatcher — this loom owns no kotlinx.coroutines.CoroutineScope and launches nothing. There is no work here for a dispatcher to schedule.

Constructors

Link copied to clipboard
constructor(policy: DeliveryPolicy = DeliveryPolicy.Reliable)

Properties

Link copied to clipboard
val peers: StateFlow<Set<PeerId>>

Functions

Link copied to clipboard

Whether this fabric can be attempted now — the availability half of capability. Derived; do not override.

Link copied to clipboard
open override fun capability(): TransportCapability

FabricAvailability.Available is a fact here, not the guess Loom.capability()'s floor exists to refuse (#1746): this fabric is the object itself. It opens no socket, acquires no OS resource, needs no permission and reaches no remote, so there is nothing left that could make a weave unattemptable. Roleless because no TransportRole describes an in-process mesh.

Link copied to clipboard
open suspend fun host(pattern: Pattern): Seam

Host / start a new session.

Link copied to clipboard
open suspend fun join(tag: Tag): Seam

Join an existing session. The advertisement carries enough info to reach the existing peer set.

Link copied to clipboard
open suspend override fun weave(rendezvous: Rendezvous): Seam

Establish a Seam according to rendezvous — either host a new session or join an existing one.