Skip to content
Bluetape4k docs1.11

Future and coroutine boundaries

Latest stable Based on Bluetape4k release 1.11.0

Redisson exposes synchronous and RFuture APIs. A coroutine service should call async methods and await() rather than mixing blocking get() calls. Coroutine syntax does not turn a synchronous Redis call into non-blocking I/O.

suspend fun loadProfiles(client: RedissonClient, ids: List<String>): List<Profile?> {
val map = client.getMap<String, Profile>("profiles")
return ids.map { map.getAsync(it) }.awaitAll()
}

awaitAll() returns an empty list for an empty collection, preserves input order, and propagates a failure instead of returning a partial list.

Iterable<RFuture<V>>.sequence() creates a CompletableFuture<List<V>> and defaults to the virtual-thread executor. awaitAll() uses the current coroutine dispatcher as its executor, falling back to Dispatchers.Default. These functions combine futures that already exist; they do not provide concurrency limits.

For large ID lists, chunk requests or use a Redisson bulk operation rather than creating an unbounded number of commands first.

withSuspendedBatch registers commands and awaits executeAsync(). Use async methods inside the DSL. It is a round-trip optimization, not a transaction.

withSuspendedTransaction awaits commit and, after failure, attempts async rollback before rethrowing the original failure. Cancellation raised while awaiting rollback remains cancellation.

client.withSuspendedTransaction {
getMap<String, Long>("balances").putAsync("42", 1_000L)
}

Cancellation does not guarantee that Redis cancels a command already sent to the server. Retried operations need request IDs, compare-and-set, or another deduplication rule.

Converting every timeout, decode error, or cancellation to null makes an outage look like a normal cache miss. Even optional cache reads should distinguish miss from backend failure and emit a metric.