I found this repository at GitHub Long Polling Redis
So in spring boot, we can use a deferred request to hold the client request for several seconds (AppMsgController.java#L72)
and it will send back to the client until the deferred request is filled with the result (AppMsgHandler.java#L74) or until it reaches the timeout.
I also notice this mechanism also can be implemented with CompetableFuture in java using completeOnTimeout.
But I wonder can we use something similar in Kotlin Coroutines?
2
Answers
In Kotlin coroutines there is the
Deferred
type, which is similar toCompletableFuture
in the sense that it represents a value that is not yet available but probably will be in the future (if no error occurs/exception is thrown). @Joffrey pointed out that there is also aCompletableDeferred
, which is even closer toComplatableFuture
enabling the user to manually callcomplete
orexceptionallyComplete
.Deferreds can easily be created with the
async
extension function onCoroutineScope
. If you want to set a timeout, Kotlin has you covered with thewithTimeout
function that cancels the block of code after a given time.Note that
withTimeout
should be insideasync
and not the other way around.Take a look at this example: https://pl.kotl.in/uYe12ds7g
As @Spitzbueb said, you could do something similar with
CompletableDeferred
.However, if you don’t need to support the
clear()
andcount()
methods, you could also probably simplify by replacing theConcurrentHashMap
with a simpleMutableSharedFlow<Unit>
that broadcasts "pings" from redis.In
onMessage
, you could emitUnit
into the mutable shared flow to notify subscribers, and then you can simply implement your request mechanism by awaiting the first element on the shared flow and making thereadSubset
request:The controller can then simply call
requestMessages
(provided you make your controller usesuspend
functions with Spring WebFlux).