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>() 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" } }