multiple onConnect in sessions support

This commit is contained in:
Sergey Chernov 2024-11-19 18:20:53 +07:00
parent 1032eebbbe
commit f2d8330ccc
5 changed files with 43 additions and 11 deletions

View File

@ -156,8 +156,19 @@ class KiloClient<S>(
var secretIdKey: SigningKey? = null
/**
* Build local command implementations (remotely callable ones), exception
* class handlers, etc.
* Build local command implementations, those callable from the server, exception
* class handlers, and anything else [KiloInterface] allows. Usage sample:
*
* ```kotlin
* val client = KiloClient {
* connect { connectTcpDevice("localhost:$port") }
* local {
* on(cmdPing) {
* "pong! $it"
* }
* }
* }
* ```
*/
fun local(f: KiloInterface<S>.() -> Unit) {
interfaceBuilder = f

View File

@ -80,7 +80,7 @@ class KiloClientConnection<S>(
kiloRemoteInterface.complete(
KiloRemoteInterface(deferredParams, clientInterface)
)
clientInterface.onConnectHandler?.invoke(params.scope)
clientInterface.onConnectHandlers.invokeAll(params.scope)
onConnectedStateChanged?.invoke(true)
job.join()
@ -104,4 +104,7 @@ class KiloClientConnection<S>(
override suspend fun <A> push(cmd: Command<A, Unit>, args: A) {
kiloRemoteInterface.await().push(cmd, args)
}
}
}
internal fun <S>Collection<KiloHandler<S>>.invokeAll(scope: KiloScope<S>) =
forEach { runCatching { scope.it() } }

View File

@ -1,5 +1,6 @@
package net.sergeych.kiloparsec
typealias KiloHandler<S> = KiloScope<S>.()->Unit
/**
* The local interface to provide functions, register errors for Kiloparsec users. Use it
* with [KiloClient], [KiloClientConnection], [KiloServerConnection], etc.
@ -14,9 +15,16 @@ package net.sergeych.kiloparsec
*/
open class KiloInterface<S> : LocalInterface<KiloScope<S>>() {
internal var onConnectHandler: (KiloScope<S>.()->Unit) ? = null
internal val onConnectHandlers = mutableListOf<KiloHandler<S>>()
fun onConnected(f: KiloScope<S>.()->Unit) { onConnectHandler = f }
/**
* Registers handler [f] for [onConnected] event, to the head or the end of handler list.
*
* @param addFirst if true, [f] will be added to the beginning of the list of handlers
*/
fun onConnected(addFirst: Boolean = false, f: KiloScope<S>.()->Unit) {
if( addFirst ) onConnectHandlers.add(0, f) else onConnectHandlers += f
}
init {
registerError { RemoteInterface.UnknownCommand(it) }

View File

@ -75,7 +75,7 @@ class KiloServerConnection<S>(
kiloRemoteInterface.complete(
KiloRemoteInterface(deferredParams, clientInterface)
)
clientInterface.onConnectHandler?.invoke(p.scope)
clientInterface.onConnectHandlers.invokeAll(p.scope)
}
}

View File

@ -26,9 +26,11 @@ class InternetTest {
val cmdSave by command<String, Unit>()
val cmdLoad by command<Unit, String>()
val cmdDrop by command<Unit, Unit>()
val cmdPing by command<String, String>()
val cmdException by command<Unit, Unit>()
val cmdCallClient by command<String, String>()
val cli = KiloInterface<Session>().apply {
val serverInterface = KiloInterface<Session>().apply {
registerError { TestException() }
onConnected { session.data = "start" }
on(cmdSave) { session.data = it }
@ -41,18 +43,26 @@ class InternetTest {
on(cmdDrop) {
throw LocalInterface.BreakConnectionException()
}
on(cmdCallClient) {
remote.call(cmdPing, it)
}
}
val server = KiloServer(cli, acceptTcpDevice(port)) {
val server = KiloServer(serverInterface, acceptTcpDevice(port)) {
Session("unknown")
}
data class LocalSession(val localFoo: String)
val client = KiloClient {
addErrors(cli)
addErrors(serverInterface)
session { LocalSession("unknown") }
// TODO: add register error variant
connect { connectTcpDevice("localhost:$port") }
local {
on(cmdPing) {
"pong! $it"
}
}
}
assertEquals("start", client.call(cmdLoad))
@ -68,7 +78,7 @@ class InternetTest {
// reconnect?
assertEquals("start", client.call(cmdLoad))
assertEquals("pong! 42", client.call(cmdCallClient, "42"))
server.close()
}