Skip to content
Bluetape4k docs1.11

Synchronous and suspend JCache

Latest stable Based on Bluetape4k release 1.11.0

LettuceCaches exposes the common creation paths. The synchronous path returns JCache<K, V>, while the coroutine path returns LettuceSuspendJCache<V> with String keys.

val sessions = LettuceCaches.jcache<String, Session>(
redisClient, "sessions-v1", ttlSeconds = 1_800,
)
val suspended = LettuceCaches.suspendJCache<Session>(
redisClient, "sessions-suspend-v1", ttlSeconds = 1_800,
)

Both wrap the Redis-hash LettuceJCache. The suspend type is an adapter that runs blocking JCache calls on Dispatchers.IO, not a separate fully non-blocking implementation.

getAll reads keys in chunks of 100. putAll performs one existing-field read only when listeners are present, then distinguishes CREATED from UPDATED events.

sessions.putAll(mapOf("a" to sessionA, "b" to sessionB))
val found = sessions.getAll(setOf("a", "b", "missing"))
check(found.keys == setOf("a", "b"))

replace(key, old, new) and remove(key, old) read and compare before issuing another Redis command. They are not distributed compare-and-set operations. Use the near-cache Lua CAS or a dedicated Redis script when the comparison must be atomic.

Entry listeners observe CREATED, UPDATED, and REMOVED operations executed by this cache instance. Writes from another Redis client do not automatically become JCache listener events.

The 1.11.0 implementation supports invoke and invokeAll with a MutableEntry. A requested change is committed through the normal JCache write path after processor execution.

val count = sessions.invoke("a", EntryProcessor<String, Session, Int> { entry, _ ->
val next = entry.value!!.copy(refreshCount = entry.value!!.refreshCount + 1)
entry.setValue(next)
next.refreshCount
})

This is not wrapped in one Redis transaction or Lua script, so concurrent external changes can race with it.

The suspend wrapper dispatches CRUD and close calls to Dispatchers.IO. entries() and getAll(keys) return Flow, but their source is still synchronous JCache work.

putAllFlow collects and writes each pair separately. Collect into a map and call putAll when a Redis batch is required.

LettuceSuspendCacheManager reuses wrappers by name and applies default TTL and codec values. closeCache removes a wrapper but preserves Redis data, allowing another wrapper to read it. Use destroyCache or clear when data must be deleted.

Its suspend close() tries to close all registered caches. If one close throws CancellationException, it finishes the remaining cleanup and then rethrows cancellation.