!refactored session to WithAdapter based to propery run many connections on the server
This commit is contained in:
parent
f455f2b955
commit
07f9e720a1
@ -10,7 +10,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "net.sergeych"
|
||||
version = "0.1.0-SNAPSHOT"
|
||||
version = "0.1.1-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -8,7 +8,6 @@ import net.sergeych.boss_serialization.BossDecoder
|
||||
import net.sergeych.boss_serialization_mp.BossEncoder
|
||||
import net.sergeych.boss_serialization_mp.decodeBoss
|
||||
import net.sergeych.mp_logger.LogTag
|
||||
import net.sergeych.mp_logger.debug
|
||||
import net.sergeych.mp_logger.exception
|
||||
import net.sergeych.mp_logger.warning
|
||||
import net.sergeych.mptools.toDump
|
||||
@ -67,7 +66,7 @@ import net.sergeych.mptools.toDump
|
||||
* parsec3 built-in exceptions.
|
||||
* @param sendEncoded a method that performs actual sending of the packed binary frame to the remote side
|
||||
*/
|
||||
open class Adapter<T>(
|
||||
open class Adapter<T: WithAdapter>(
|
||||
private val instance: T,
|
||||
private val commandHost: CommandHost<T>,
|
||||
private val exceptionRegistry: ExceptionsRegistry = ExceptionsRegistry(),
|
||||
@ -95,14 +94,14 @@ open class Adapter<T>(
|
||||
return CompletableDeferred<ByteArray>().also { dr ->
|
||||
sendPackage(
|
||||
access.withLock {
|
||||
debug { "calling $lastId:${ca.name}($args)" }
|
||||
// debug { "calling $lastId:${ca.name}($args)" }
|
||||
completions[lastId] = dr
|
||||
myId = lastId
|
||||
Package.Command(lastId++, ca.name, BossEncoder.encode(ca.ass, args))
|
||||
}
|
||||
)
|
||||
}.await().let {
|
||||
debug { "result $myId:$it" }
|
||||
// debug { "result $myId:$it" }
|
||||
BossDecoder.decodeFrom(ca.rss, it)
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,19 @@ package net.sergeych.parsec3
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import net.sergeych.mp_tools.globalLaunch
|
||||
|
||||
class AdapterBuilder<S, H : CommandHost<S>>(
|
||||
open class WithAdapter {
|
||||
internal var _adapter: Adapter<*>? = null
|
||||
|
||||
val adapter: Adapter<*> get() = _adapter ?: throw IllegalStateException("adapter is not yet initialized")
|
||||
}
|
||||
|
||||
class AdapterBuilder<S : WithAdapter, H : CommandHost<S>>(
|
||||
val api: H,
|
||||
val exceptionRegistry: ExceptionsRegistry = ExceptionsRegistry(),
|
||||
f: AdapterBuilder<S, H>.() -> Unit,
|
||||
) {
|
||||
|
||||
internal var sessionProducer: (suspend () -> S) = { Unit as S}
|
||||
internal var sessionProducer: (suspend () -> S) = { WithAdapter() as S}
|
||||
private set
|
||||
|
||||
|
||||
@ -17,10 +23,6 @@ class AdapterBuilder<S, H : CommandHost<S>>(
|
||||
sessionProducer = f
|
||||
}
|
||||
|
||||
private var _adapter: Adapter<S>? = null
|
||||
|
||||
val adapter: Adapter<S> get() = _adapter ?: throw IllegalStateException("adapter is not yet initialized")
|
||||
|
||||
/**
|
||||
* Register command implementation
|
||||
*/
|
||||
@ -33,15 +35,18 @@ class AdapterBuilder<S, H : CommandHost<S>>(
|
||||
}
|
||||
|
||||
suspend fun createWith(input: Flow<ByteArray>, f: suspend (ByteArray)->Unit ): Adapter<S> {
|
||||
return Adapter<S>(sessionProducer(), api, exceptionRegistry) { f(it) }
|
||||
val s = sessionProducer()
|
||||
return Adapter<S>(
|
||||
s, api, exceptionRegistry) { f(it) }
|
||||
.also { a->
|
||||
s._adapter = a
|
||||
globalLaunch { input.collect { a.receiveFrame(it)} }
|
||||
_adapter = a
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun create(f: suspend (ByteArray) -> Unit): Adapter<S> {
|
||||
return Adapter(sessionProducer(), api, exceptionRegistry, f)
|
||||
val s = sessionProducer()
|
||||
return Adapter(s, api, exceptionRegistry, f).also { s._adapter = it }
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -13,7 +13,7 @@ class CommandDescriptor<A, R>(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
suspend operator fun invoke(adapter: Adapter<*>): R = adapter.invokeCommand(this,Unit as A)
|
||||
|
||||
operator fun <I>invoke(commandHost: CommandHost<I>, block: suspend I.(A)->R) {
|
||||
operator fun <I: WithAdapter>invoke(commandHost: CommandHost<I>, block: suspend I.(A)->R) {
|
||||
commandHost.on(this, block)
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import kotlin.reflect.typeOf
|
||||
*
|
||||
* @param T the type of the `state` instance used to hold state, use `Unit` for stateless interfaces
|
||||
*/
|
||||
open class CommandHost<T> {
|
||||
open class CommandHost<T: WithAdapter> {
|
||||
private val handlers = mutableMapOf<String, suspend T.(ByteArray) -> ByteArray>()
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
* asynchronous (push capable) calls, but normally it should be used as a transport for parsec 3.1 secure
|
||||
* protocol which uses this transport interface to run.
|
||||
*/
|
||||
interface Parsec3Transport<S> {
|
||||
interface Parsec3Transport<S: WithAdapter> {
|
||||
val connectedFlow: StateFlow<Boolean>
|
||||
fun close()
|
||||
|
||||
|
@ -11,7 +11,7 @@ import net.sergeych.mp_logger.LogTag
|
||||
import net.sergeych.mp_logger.info
|
||||
import net.sergeych.mp_tools.globalLaunch
|
||||
|
||||
class Parsec3WSClient<S, H : CommandHost<S>>(
|
||||
class Parsec3WSClient<S: WithAdapter, H : CommandHost<S>>(
|
||||
val url: String,
|
||||
val api: H,
|
||||
val exceptionsRegistry: ExceptionsRegistry = ExceptionsRegistry(),
|
||||
|
@ -11,14 +11,14 @@ import kotlin.test.assertEquals
|
||||
|
||||
internal class AdapterTest {
|
||||
|
||||
object Api1 : CommandHost<Unit>() {
|
||||
object Api1 : CommandHost<WithAdapter>() {
|
||||
// create command `foo` that takes a string argument and
|
||||
// returns a string:
|
||||
val foo by command<String, String>()
|
||||
}
|
||||
|
||||
|
||||
object Api2 : CommandHost<Unit>() {
|
||||
object Api2 : CommandHost<WithAdapter>() {
|
||||
|
||||
val bar by command<String, String>()
|
||||
}
|
||||
@ -36,8 +36,8 @@ internal class AdapterTest {
|
||||
it + "bar"
|
||||
}
|
||||
|
||||
val a1 = Adapter(Unit, api1) { ch12.send(it) }
|
||||
val a2 = Adapter(Unit, api2) { ch21.send(it) }
|
||||
val a1 = Adapter(WithAdapter(), api1) { ch12.send(it) }
|
||||
val a2 = Adapter(WithAdapter(), api2) { ch21.send(it) }
|
||||
launch { for (b in ch12) a2.receiveFrame(b) }
|
||||
launch { for (b in ch21) a1.receiveFrame(b) }
|
||||
|
||||
@ -49,7 +49,7 @@ internal class AdapterTest {
|
||||
|
||||
}
|
||||
|
||||
data class TestSession(var buzz: String)
|
||||
data class TestSession(var buzz: String) : WithAdapter()
|
||||
|
||||
object ApiS1 : CommandHost<TestSession>() {
|
||||
// create command `foo` that takes a string argument and
|
||||
@ -58,7 +58,7 @@ internal class AdapterTest {
|
||||
val ex by command<String,Unit>()
|
||||
val ex2 by command<String,Unit>()
|
||||
}
|
||||
class ApiS2<T> : CommandHost<T>() {
|
||||
class ApiS2<T: WithAdapter> : CommandHost<T>() {
|
||||
// create command `foo` that takes a string argument and
|
||||
// returns a string:
|
||||
val bar by command<String, String>()
|
||||
@ -86,8 +86,7 @@ internal class AdapterTest {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
val b2 = AdapterBuilder(ApiS2<Unit>(), er) {
|
||||
newSession { }
|
||||
val b2 = AdapterBuilder(ApiS2(), er) {
|
||||
on(api.bar) {
|
||||
it + "bar"
|
||||
}
|
||||
@ -111,7 +110,7 @@ internal class AdapterTest {
|
||||
}
|
||||
|
||||
// assertEquals("123bar", a1.invokeCommand(ApiS2<Unit>().bar, "123"))
|
||||
assertEquals("%% loop-42foo %%", a1.invokeCommand(ApiS2<Unit>().loopCall, "123"))
|
||||
assertEquals("%% loop-42foo %%", a1.invokeCommand(ApiS2<WithAdapter>().loopCall, "123"))
|
||||
assertEquals("32142foo", a2.invokeCommand(ApiS1.foo, "321"))
|
||||
|
||||
assertEquals("---42foo", ApiS1.foo.invoke(a2, "---"))
|
||||
|
@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicLong
|
||||
* Creates a ktor server initialization module capable to perform p3 transport layer (not secure).
|
||||
* It could be used as is or as transport for p3.1
|
||||
*/
|
||||
fun <S, H : CommandHost<S>>Application.parsec3TransportServer(
|
||||
fun <S: WithAdapter, H : CommandHost<S>>Application.parsec3TransportServer(
|
||||
api: H,
|
||||
exceptionsRegistry: ExceptionsRegistry = ExceptionsRegistry(),
|
||||
path: String = "/api/p3",
|
||||
|
@ -8,12 +8,12 @@ import kotlin.test.assertEquals
|
||||
|
||||
internal class WsServerKtTest {
|
||||
|
||||
data class TestSession(var buzz: String = "BuZZ")
|
||||
data class TestSession(var buzz: String = "BuZZ"): WithAdapter()
|
||||
|
||||
object TestApiServer: CommandHost<TestSession>() {
|
||||
val foo by command<String,String>()
|
||||
}
|
||||
object TestApiClient: CommandHost<Unit>() {
|
||||
object TestApiClient: CommandHost<WithAdapter>() {
|
||||
val bar by command<String,String>()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user