FlakyLifecycleSeam
A Seam wrapper that owns its own state and gates the contract on it, enabling lifecycle-flap scenarios in tests.
Unlike FaultySeam (which delegates state and injects per-frame faults), this wrapper can simulate a transport link that drops and recovers: Woven → Weaving → Woven (transient reconnect) or escalates to Torn (permanent failure).
Behaviour while SeamState.Weaving
peers collapses to
{selfId}— this peer is momentarily alone.broadcast is the contract's defined no-op (no other peers; returns immediately without throwing).
sendTo throws PeerNotConnected for any absent peer (as always).
Inbound frames from the delegate are dropped while weaving — they are not buffered and will not appear on incoming after recover.
Behaviour on recover
state → Woven, peers refills from the delegate, inbound delivery resumes.
Behaviour on tear
state → Torn(reason) (terminal), incoming completes, subsequent sends throw IllegalStateException.
Composition
Lifecycle wrapper outer, frame-fault inner: FlakyLifecycleSeam(FaultySeam(realSeam), scope). The lifecycle wrapper gates the consumer-facing contract on its own state; the inner FaultySeam applies frame-level faults to whatever flows while SeamState.Woven.
Determinism guarantee: all timing goes through kotlinx.coroutines.delay so kotlinx.coroutines.test.runTest controls virtual time. FlapSchedule jitter is seeded — same seed, same flap pattern.
Functions
Suspend through weavingFor in SeamState.Weaving then return to SeamState.Woven — one atomic blip.
Disconnect from the session. Idempotent.
Launch a FlapSchedule loop in scope and return the running Job.
Perform flaps blips (each SeamState.Weaving for weavingFor), then tear with reason. After this call completes the seam is terminal.
Transition to SeamState.Torn (terminal). incoming completes; subsequent sends throw IllegalStateException.