Describe the bug
After establishing a websocket connection for KRPC using KtorRpcClient, and the restarting the server so that this connection is lost, web-targets (JS/WASM) are not able to handle Exceptions so that the connection can be manually recreated.
The following solutions to re-establish a connection works fine on Desktop target, but on Web nothing happens: no errors, no timeouts, nothing.
I've tried to set timeouts, use @Volatile and some other solutions to take the more asyncronous events in the browser into consideration; none of which worked on web.
It seems that the actual client on web never throws an exception or the transpiled code isn't handling the exception.
To Reproduce
Following code is the most simple approach that works fine on desktop.
- Start Backend & Frontend
- Use Frontend
- Restart Server
- Try another action in Frontend -> Dead
class ApiClient(
private val baseUrl: String = "http://localhost:8080"
) {
private val rpcClient = HttpClient(){
installKrpc {
serialization {
json(Json {
serializersModule = SerializersModule {
include(ArrowModule)
}
})
}
}
}
private var _rpcConnection: kotlinx.rpc.krpc.ktor.client.KtorRpcClient? = null
private var _crudRpcService: RpcCrudService? = null
// other RpcServices defined as well
private suspend fun createConnection(): kotlinx.rpc.krpc.ktor.client.KtorRpcClient {
return rpcClient.rpc {
url {
host = "localhost"
port = 8080
encodedPath = "/rpc"
}
}
}
private suspend inline fun <reified T> getOrCreateService(): T {
val connection = _rpcConnection ?: createConnection().also { _rpcConnection = it }
return when (T::class) {
RpcCrudService::class -> _crudRpcService ?: connection.withService<RpcCrudService>().also { _crudRpcService = it }
else -> error("Unknown service type: ${T::class}")
} as T
}
suspend inline fun <R> withCrudService(block: suspend (RpcCrudService) -> R): R {
return try {
block(getOrCreateService<RpcCrudService>())
} catch (e: Exception) {
_rpcConnection = null
_crudRpcService = null
// other Rpc services reset here as well
block(getOrCreateService<RpcCrudService>())
}
}
}
Expected behavior
Web-Targets work the same as Desktop, meaning the manual reconnection works. An internal reconnection mechanism would be preferable. Also a documented best-practise would be nice (server-restarts need to be taken into account nowadays)
Additional context
Kotlin: 2.3.0
Gradle: 8.14.3
OS: Linux
KMP: 1.9.3
Ktor: 3.3.3
The only thing that worked was to force a new connection on every request (very bad) or to handle a connection as stale after it has not been used for 30s, which still result in very poor user-experience.
Describe the bug
After establishing a websocket connection for KRPC using
KtorRpcClient, and the restarting the server so that this connection is lost, web-targets (JS/WASM) are not able to handle Exceptions so that the connection can be manually recreated.The following solutions to re-establish a connection works fine on Desktop target, but on Web nothing happens: no errors, no timeouts, nothing.
I've tried to set timeouts, use
@Volatileand some other solutions to take the more asyncronous events in the browser into consideration; none of which worked on web.It seems that the actual client on web never throws an exception or the transpiled code isn't handling the exception.
To Reproduce
Following code is the most simple approach that works fine on desktop.
Expected behavior
Web-Targets work the same as Desktop, meaning the manual reconnection works. An internal reconnection mechanism would be preferable. Also a documented best-practise would be nice (server-restarts need to be taken into account nowadays)
Additional context
Kotlin: 2.3.0
Gradle: 8.14.3
OS: Linux
KMP: 1.9.3
Ktor: 3.3.3
The only thing that worked was to force a new connection on every request (very bad) or to handle a connection as stale after it has not been used for 30s, which still result in very poor user-experience.