appChannel
Returns the application Seam for the channel named name, idempotent per name.
The returned seam is single-collection like any other: collect its Seam.incoming once, fan out with shareIn if needed.
Throws
if name's UTF-8 encoding is empty or exceeds 255 bytes.
Samples
runTest(StandardTestDispatcher(), timeout = 5.seconds) {
val loom = InMemoryLoom()
val seamAlice = loom.host(Pattern("my-game"))
val seamBob = loom.join(InMemoryTag("bob"))
val id1 = NodeId(seamAlice.selfId.value)
val id2 = NodeId(seamBob.selfId.value)
val voterIds = setOf(id1, id2)
val alice = backgroundScope.gameNode(seamAlice, voterIds, raftConfig = RaftConfig(expectVirtualTime = true))
val bob = backgroundScope.gameNode(seamBob, voterIds, raftConfig = RaftConfig(expectVirtualTime = true))
// Both peers attach a Quilter<Rga<String>> to the "chat" app channel.
val chatMsgSer = QuiltMessage.serializer(Rga.wireSerializer(serializer<String>()))
val aliceChat = Quilter(
replica = ReplicaId(seamAlice.selfId.value),
seam = alice.appChannel("chat"),
initial = Rga.empty(),
messageSerializer = chatMsgSer,
scope = backgroundScope,
config = QuilterConfig(expectVirtualTime = true),
)
val bobChat = Quilter(
replica = ReplicaId(seamBob.selfId.value),
seam = bob.appChannel("chat"),
initial = Rga.empty(),
messageSerializer = chatMsgSer,
scope = backgroundScope,
config = QuilterConfig(expectVirtualTime = true),
)
// Each peer appends a message to its local RGA replica, then broadcasts the delta.
fun Quilter<Rga<String>>.chat(msg: String) {
val (_, op) = state.value.insertAfter(replica, RgaId.HEAD, msg)
apply(Patch(Rga.empty<String>().apply(op)))
}
aliceChat.chat("alice: hello")
bobChat.chat("bob: hello")
delay(10) // advance virtual time so delta broadcasts deliver to both peers
// Both RGAs converge to the same ordered log of two messages.
assertEquals(aliceChat.state.value.toList(), bobChat.state.value.toList())
assertEquals(2, aliceChat.state.value.toList().size)
alice.close()
bob.close()
}Content copied to clipboard