Add prioritized transport, bounded reconnect, and configurable keepalive

Carry numeric priorities through encrypted RPC and adapter writers with bounded admission. Correct push semantics and socket lifecycle cleanup, expose dispatch gating, and add opt-in connection health.

Preserve the WebSocket setup API while allowing applications to override keepalive settings. Enable Android socket publication and document the 0.7.2-SNAPSHOT release workflow.
This commit is contained in:
sergeych committed 2026-10-15 08:36:34 +04:00
1 parent 0a52bb5c03
commit 617f22dda1
27 files changed
+1154 -295

No files matched your search

@@ -0,0 +1,65 @@
@file:OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class, ExperimentalUnsignedTypes::class)
import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
import net.sergeych.crypto2.initCrypto
import net.sergeych.kiloparsec.*
import kotlin.test.*
import kotlin.time.Duration.Companion.seconds
class TransportAdmissionTest {
@Test fun readyCallsDoNotAddPollingDelay() = runTest(timeout = 10.seconds) {
val ping by command<Int, Int>()
val (a, b) = createTestDevice()
val local = LocalInterface<Unit>().apply { on(ping) { it } }
val client = Transport(a, local, Unit)
val server = Transport(b, local, Unit)
val jobs = listOf(launch { client.run() }, launch { server.run() })
try {
val start = currentTime
repeat(20) { assertEquals(it, client.call(ping, it)) }
assertEquals(0L, currentTime - start, "Ready transports must not impose an artificial per-call delay")
} finally { jobs.forEach { it.cancelAndJoin() } }
}
@Test fun successfulPlainPushReturnsNormally() = runTest(timeout = 10.seconds) {
val notify by command<Int, Unit>()
val received = CompletableDeferred<Int>()
val (a, b) = createTestDevice()
val client = Transport(a, LocalInterface<Unit>(), Unit)
val server = Transport(b, LocalInterface<Unit>().apply { on(notify) { received.complete(it); Unit } }, Unit)
val jobs = listOf(launch { client.run() }, launch { server.run() })
try {
client.push(notify, 7)
assertEquals(7, received.await())
} finally { jobs.forEach { it.cancelAndJoin() } }
}
@Test fun encryptedPushDoesNotWaitForRemoteHandler() = runTest(timeout = 10.seconds) {
initCrypto()
val notify by command<Int, Unit>()
val ping by command<Int, Int>()
val entered = CompletableDeferred<Unit>()
val release = CompletableDeferred<Unit>()
val ready = CompletableDeferred<Unit>()
val (a, b) = createTestDevice()
val server = KiloServerConnection(KiloInterface<Unit>().apply {
on(notify) { entered.complete(Unit); release.await() }
on(ping) { it }
}, b, Unit)
val client = KiloClientConnection(KiloInterface<Unit>(), a, Unit)
val jobs = listOf(launch { server.run() }, launch { client.run { if (it) ready.complete(Unit) } })
try {
ready.await()
val notification = async { client.push(notify, 7) }
entered.await()
runCurrent()
assertTrue(notification.isCompleted, "Push must return before the remote handler finishes")
notification.await()
assertEquals(9, client.call(ping, 9), "A pending notification must not block ordinary RPC")
} finally {
release.complete(Unit)
jobs.forEach { it.cancelAndJoin() }
}
}
}