Skip to content

Commit

Permalink
Merge pull request #6 from sksamuel/feature/bulk_load
Browse files Browse the repository at this point in the history
Added buildAll method
  • Loading branch information
sksamuel authored Apr 2, 2023
2 parents 2cdf4b5 + a550677 commit fe466a6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
31 changes: 31 additions & 0 deletions aedile-core/src/main/kotlin/com/sksamuel/aedile/core/caffeine.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sksamuel.aedile.core

import com.github.benmanes.caffeine.cache.AsyncCacheLoader
import com.github.benmanes.caffeine.cache.Caffeine
import com.github.benmanes.caffeine.cache.Expiry
import com.github.benmanes.caffeine.cache.RemovalCause
Expand All @@ -12,6 +13,8 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.future.asCompletableFuture
import kotlinx.coroutines.launch
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executor
import kotlin.time.Duration
import kotlin.time.toJavaDuration

Expand Down Expand Up @@ -170,5 +173,33 @@ class Builder<K, V>(
fun build(compute: suspend (K) -> V): LoadingCache<K, V> {
return LoadingCache(scope, caffeine.buildAsync { key, _ -> scope.async { compute(key) }.asCompletableFuture() })
}

/**
* Returns a [Cache] which suspends when requesting values.
*
* If a requested key does not exist, then the suspendable [compute] function is invoked
* to compute the required values.
*
* If the suspendable computation throws or computes a null value then the
* entry will be automatically removed.
*
*/
fun buildAll(compute: suspend (Set<K>) -> Map<K, V>): LoadingCache<K, V> {
return LoadingCache(
scope,
caffeine.buildAsync(object : AsyncCacheLoader<K, V> {
override fun asyncLoad(key: K, executor: Executor?): CompletableFuture<V> {
return asyncLoadAll(setOf(key), executor).thenApply { results -> results[key] }
}

override fun asyncLoadAll(
keys: Set<K>,
executor: Executor?,
): CompletableFuture<Map<K, V>> {
return scope.async { compute(keys) }.asCompletableFuture()
}
})
)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ class LoadingCacheTest : FunSpec() {
cache.get("else") shouldBe "bar"
}

test("LoadingCache should use support suspendable multiple keys loading function") {
val cache = caffeineBuilder<String, String>().buildAll {
delay(1)
mapOf("tweedle" to "dee", "twuddle" to "dum")
}
cache.get("tweedle") shouldBe "dee"
cache.get("twuddle") shouldBe "dum"
}

test("LoadingCache should support simple puts") {
val cache = caffeineBuilder<String, String>().build()
cache.put("foo", "bar")
Expand Down

0 comments on commit fe466a6

Please sign in to comment.