Created
September 29, 2023 09:30
-
-
Save ChrisBlom/4fe924de2234dfc868b490a3f7e1f254 to your computer and use it in GitHub Desktop.
how to wrap a function in Kotlin so that is invoked at most once in a duration for each argument
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.github.benmanes.caffeine.cache.Caffeine | |
import com.github.benmanes.caffeine.cache.Ticker | |
import io.kotest.matchers.shouldBe | |
import org.junit.jupiter.api.Test | |
import java.util.concurrent.ConcurrentHashMap | |
import java.util.concurrent.atomic.AtomicLong | |
import kotlin.time.Duration | |
import kotlin.time.Duration.Companion.seconds | |
import kotlin.time.toJavaDuration | |
class CachedFor { | |
fun <A : Any, B : Any> cachedFor( | |
duration: Duration, | |
ticker: Ticker = Ticker.systemTicker(), | |
f: (A) -> B | |
): (A) -> B { | |
val cache = Caffeine | |
.newBuilder() | |
.ticker(ticker) | |
.expireAfterWrite(duration.toJavaDuration()) | |
.build(f) | |
return { x -> cache.get(x) } | |
} | |
@Test | |
fun test() { | |
val time = AtomicLong(0) | |
val ticker = Ticker { time.get() } | |
val advanceTicker = { duration: Duration -> time.addAndGet(duration.inWholeNanoseconds) } | |
val invocations = ConcurrentHashMap<String, Int>() | |
val cachedAdd = cachedFor(duration = 1.seconds, ticker = ticker) { x: String -> | |
val c = invocations.compute(x) { _, v -> (v ?: 0) + 1 } | |
x.repeat(2) | |
} | |
repeat(10) { cachedAdd("x") shouldBe "xx" } | |
invocations shouldBe mapOf("x" to 1) | |
advanceTicker(1.seconds) | |
repeat(10) { cachedAdd("x") shouldBe "xx" } | |
invocations shouldBe mapOf("x" to 2) | |
repeat(10) { cachedAdd("y") shouldBe "yy" } | |
invocations shouldBe mapOf("x" to 2, "y" to 1) | |
advanceTicker(1.seconds) | |
repeat(10) { cachedAdd("y") shouldBe "yy" } | |
invocations shouldBe mapOf("x" to 2, "y" to 2) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment