콘텐츠로 이동
Bluetape4k 문서1.11

Redisson JCache와 suspend wrapper

최신 안정판 Bluetape4k 1.11.0 릴리스 기준

RedissonJCaching은 Redisson의 JCachingProvider를 사용해 표준 javax.cache.Cache를 만들고, RedissonSuspendJCache는 같은 cache를 SuspendJCache로 감쌉니다. RedissonCaches factory를 쓰면 두 경로를 한 곳에서 선택할 수 있습니다.

val cache = RedissonCaches.suspendJCache<String, User>(
redisson = redissonClient,
cacheName = "users",
configuration = MutableConfiguration<String, User>().apply {
setTypes(String::class.java, User::class.java)
},
)
cache.put("u:1", User("u:1", "debop"))
val user = cache.get("u:1")

RedissonClient를 넘기면 애플리케이션이 client를 계속 소유합니다. Config overload는 provider가 client 생성에 관여하므로 manager와 client 종료 정책을 애플리케이션 lifecycle 문서에 남깁니다.

RedissonJCaching.cacheManager는 lazy singleton입니다. getOrCreate는 같은 이름 cache가 있으면 재사용합니다. 따라서 기존 cache의 key/value type이나 configuration과 새 호출이 어긋나면 새 설정이 적용된다고 기대하면 안 됩니다.

테스트는 고유 cache 이름을 사용하고 종료할 때 clear 또는 close합니다. 서비스에서는 cache 이름을 데이터 계약으로 취급하고 환경·tenant 경계를 이름에 반영합니다.

CRUD 대부분은 Redisson JCache의 *Async()를 호출하고 await()합니다. putAllFlow는 각 put을 deferred로 바꾼 뒤 joinAll()로 모두 끝날 때까지 기다립니다. entries()는 JCache iterator를 순회하므로 대량 scan을 가벼운 non-blocking stream으로 오해하지 않습니다.

removeAll()은 async overload 대신 Dispatchers.IO에서 blocking method를 호출합니다. API가 suspend라는 사실만으로 provider의 모든 내부 작업이 non-blocking이라는 뜻은 아닙니다.

1.11.0의 getAndPut은 Redisson JCache가 getAndPutAsync()를 제공하지 않아 get(key) 다음 put(key, value)를 실행합니다.

val previous = cache.getAndPut("u:1", updated)

두 호출 사이에 다른 writer가 값을 바꾸면 previous와 최종 값이 하나의 원자 연산 결과가 아닐 수 있습니다. compare-and-set이나 엄격한 read-modify-write가 필요하면 Redisson RMap의 원자 API를 직접 사용합니다.

close()는 감싼 JCache를 닫지만 저장된 entry를 삭제하지 않습니다. entry 정리는 clear() 또는 removeAll()로 명시합니다. close 중 일반 예외는 warning으로 남기고, CancellationException은 호출자에게 다시 던집니다.