Spring Boot Web Flux with JOOQ for interfacing with DB and Kotlin coroutines to make blocking JDBC calls run asynchronously. Now with rsockets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

86 lines
2.9 KiB

package com.example.demo.controller
import com.example.demo.model.Message
import com.example.demo.model.User
import kotlinx.coroutines.*
import org.slf4j.LoggerFactory
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.Payload
import org.springframework.messaging.rsocket.RSocketRequester
import org.springframework.messaging.rsocket.annotation.ConnectMapping
import org.springframework.stereotype.Controller
import io.vavr.collection.Map
import org.springframework.messaging.handler.annotation.MessageExceptionHandler
@Controller
class RsocketConnectionControllerAsync : CoroutineScope {
private val log = LoggerFactory.getLogger(RsocketConnectionControllerAsync::class.java)
private val job = Job()
override val coroutineContext = Dispatchers.Unconfined + job
@ObsoleteCoroutinesApi
private val myRsocketActor = rsocketActor()
@ObsoleteCoroutinesApi
suspend fun addRequester(rSocketRequester: RSocketRequester, clientId: String) {
log.info("adding requester {}", clientId)
myRsocketActor.send(AddRequester(rSocketRequester, clientId))
}
@ObsoleteCoroutinesApi
suspend fun removeRequester(clientId: String) {
log.info("removing requester {}", clientId)
myRsocketActor.send(RemoveRequester(clientId))
}
@ObsoleteCoroutinesApi
@ConnectMapping(value = ["client-id2"])
fun onConnect(
rSocketRequester: RSocketRequester,
@Payload user: User
) {
launch(coroutineContext) {
val clientId = user.id.toString()
addRequester(rSocketRequester, clientId)
rSocketRequester
.rsocket()
.onClose()
.subscribe(null, null, {
log.info("{} just disconnected", clientId)
launch(coroutineContext) { removeRequester(clientId) }
})
}
}
@ObsoleteCoroutinesApi
@MessageMapping("private.news.2")
fun privateNews(message: Message) {
launch {
val res = CompletableDeferred<Map<String, RSocketRequester>>()
myRsocketActor.send(GetRequesters(res))
res
.await()
.filterKeys { key -> key == message.toUser || key == message.fromUser }
.values()
.forEach { requester ->
println("Sending message")
sendMessage(requester, message)
}
}
}
private fun sendMessage(requester: RSocketRequester, message: Message) =
requester
.route("user.queue.reply")
.data(message)
.send()
.subscribe()
@MessageExceptionHandler
suspend fun handleException(ex: IllegalArgumentException): String {
delay(10)
return "${ex.message} handled"
}
}