From 86f1b8f33a4bd5d08f95ed889d701dcaa821682e Mon Sep 17 00:00:00 2001 From: sksamuel Date: Thu, 17 Apr 2025 22:14:14 -0500 Subject: [PATCH 1/3] Add support for refresh/refresh all --- .../com/sksamuel/aedile/core/LoadingCache.kt | 8 +++++++ .../aedile/core/AsLoadingCacheTest.kt | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt b/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt index 2b7f76f..5952be0 100644 --- a/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt +++ b/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt @@ -175,6 +175,14 @@ class LoadingCache( cache.synchronous().invalidateAll() } + fun refresh(key: K) { + cache.synchronous().refresh(key) + } + + fun refreshAll(keys: Collection) { + cache.synchronous().refreshAll(keys) + } + private suspend fun scope(): CoroutineScope { return if (useCallingContext) CoroutineScope(coroutineContext) else defaultScope } diff --git a/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt b/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt index b13d32f..46eff64 100644 --- a/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt +++ b/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt @@ -319,6 +319,30 @@ class AsLoadingCacheTest : FunSpec() { cache.contains("bubble") shouldBe false } + test("support refresh") { + var counter = 0 + val cache = Caffeine.newBuilder().asLoadingCache { + counter++ + counter + } + cache.get("foo") shouldBe 1 + cache.refresh("foo") + cache.get("foo") shouldBe 2 + } + + test("support refresh all") { + var counter = 0 + val cache = Caffeine.newBuilder().asLoadingCache { + counter++ + counter + } + cache.get("foo") shouldBe 1 + cache.get("bar") shouldBe 2 + cache.refreshAll(setOf("foo", "bar")) + cache.get("foo") shouldBe 3 + cache.get("bar") shouldBe 4 + } + test("check invariants on expire after") { val loggerExpiry = object : Expiry { override fun expireAfterRead( From 4e3bd1979c86fd90e9672d78ba2e012df265742a Mon Sep 17 00:00:00 2001 From: sksamuel Date: Thu, 17 Apr 2025 22:16:20 -0500 Subject: [PATCH 2/3] docs --- .../kotlin/com/sksamuel/aedile/core/LoadingCache.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt b/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt index 5952be0..7432f87 100644 --- a/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt +++ b/aedile-core/src/main/kotlin/com/sksamuel/aedile/core/LoadingCache.kt @@ -175,10 +175,22 @@ class LoadingCache( cache.synchronous().invalidateAll() } + /** + * Loads a new value for the key, asynchronously. While the new value is loading the + * previous value (if any) will continue to be returned by get(key) unless it is evicted. + * + * See full docs at [com.github.benmanes.caffeine.cache.LoadingCache.refresh]. + */ fun refresh(key: K) { cache.synchronous().refresh(key) } + /** + * Loads a new value for each key, asynchronously. While the new value is loading the + * previous value (if any) will continue to be returned by get(key) unless it is evicted. + * + * See full docs at [com.github.benmanes.caffeine.cache.LoadingCache.refreshAll]. + */ fun refreshAll(keys: Collection) { cache.synchronous().refreshAll(keys) } From 18d96c21413487754ce53a85d0b2d2d2c55958f5 Mon Sep 17 00:00:00 2001 From: sksamuel Date: Thu, 17 Apr 2025 22:20:24 -0500 Subject: [PATCH 3/3] tests --- .../com/sksamuel/aedile/core/AsLoadingCacheTest.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt b/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt index 46eff64..08cbf0e 100644 --- a/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt +++ b/aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt @@ -2,6 +2,7 @@ package com.sksamuel.aedile.core import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.Expiry +import io.kotest.assertions.nondeterministic.eventually import io.kotest.assertions.throwables.shouldNotThrowAny import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.FunSpec @@ -13,6 +14,7 @@ import kotlinx.coroutines.yield import org.checkerframework.checker.index.qual.NonNegative import java.util.concurrent.atomic.AtomicInteger import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds class AsLoadingCacheTest : FunSpec() { init { @@ -327,7 +329,9 @@ class AsLoadingCacheTest : FunSpec() { } cache.get("foo") shouldBe 1 cache.refresh("foo") - cache.get("foo") shouldBe 2 + eventually(5.seconds) { + cache.get("foo") shouldBe 2 + } } test("support refresh all") { @@ -339,8 +343,10 @@ class AsLoadingCacheTest : FunSpec() { cache.get("foo") shouldBe 1 cache.get("bar") shouldBe 2 cache.refreshAll(setOf("foo", "bar")) - cache.get("foo") shouldBe 3 - cache.get("bar") shouldBe 4 + eventually(5.seconds) { + cache.get("foo") shouldBe 3 + cache.get("bar") shouldBe 4 + } } test("check invariants on expire after") {