Skip to content
Bluetape4k docs1.11

Suspend JCache and async boundaries

Latest stable Based on Bluetape4k release 1.11.0

Use ICache async operations when unwrap succeeds

Section titled “Use ICache async operations when unwrap succeeds”

HazelcastSuspendJCache tries to unwrap its JCache as ICache. When successful, get, put, remove, and replace use native async operations followed by coroutine await. Otherwise, the equivalent standard JCache call runs on Dispatchers.IO.

val cache = HazelcastCaches.suspendJCache<String, User>(hazelcast, "users-v1")
cache.put("42", user) // ICache.putAsync(...).await()
val loaded = cache.get("42") // ICache.getAsync(...).await()

A suspend signature does not mean every operation is a native Hazelcast async command. containsKey, clear, putAll, keyed getAll, and listener registration use blocking or direct JCache paths.

putAll runs one standard JCache bulk call on the IO dispatcher. putAllFlow instead collects one putAsync deferred per entry and waits with joinAll when ICache is available. A very large flow also creates a large deferred list before completion, so batch input and test cancellation timing.

In 1.11.0, getAndPut is implemented as get(key).also { put(key, value) }. Another member can change the entry between those two calls, making the returned old value differ from the actual replacement target.

Do not rely on this wrapper when the operation must be atomic. Evaluate a Hazelcast server-side atomic operation or entry processor instead. getAndRemoveAsync and getAndReplaceAsync use native compound operations when ICache is available.

close closes the JCache proxy on the IO dispatcher, not the HazelcastInstance. The release suite exercises the shared suspend JCache contract but does not pin every disconnect and cancellation timing. Add application-level tests for cancellation during large bulk operations and client reconnects.