Skip to content

Commit 02f1c73

Browse files
committed
Fix invariants on bulk and loading cache builders
1 parent 1ff5c87 commit 02f1c73

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

aedile-core/src/main/kotlin/com/sksamuel/aedile/core/builders.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fun <K : Any?, V : Any?> Caffeine<in K, in V>.asCache(scope: CoroutineScope): Ca
4545
* If the suspendable computation throws or computes a null value then the
4646
* entry will be automatically removed.
4747
*/
48-
fun <K, V> Caffeine<Any, Any>.asLoadingCache(compute: suspend (K) -> V): LoadingCache<K, V> {
48+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asLoadingCache(compute: suspend (K) -> V): LoadingCache<K, V> {
4949
val scope = CoroutineScope(Dispatchers.IO + CoroutineName("Aedile-AsyncLoadingCache-Scope") + SupervisorJob())
5050
return asLoadingCache(scope, compute)
5151
}
@@ -59,7 +59,7 @@ fun <K, V> Caffeine<Any, Any>.asLoadingCache(compute: suspend (K) -> V): Loading
5959
* If the suspendable computation throws or computes a null value then the
6060
* entry will be automatically removed.
6161
*/
62-
fun <K, V> Caffeine<Any, Any>.asLoadingCache(
62+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asLoadingCache(
6363
scope: CoroutineScope,
6464
compute: suspend (K) -> V
6565
): LoadingCache<K, V> {
@@ -78,7 +78,7 @@ fun <K, V> Caffeine<Any, Any>.asLoadingCache(
7878
* The [reloadCompute] function is invoked to refresh an entry if refreshAfterWrite
7979
* is enabled or refresh is invoked. See full docs [AsyncCacheLoader.asyncReload].
8080
*/
81-
fun <K, V> Caffeine<Any, Any>.asLoadingCache(
81+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asLoadingCache(
8282
compute: suspend (K) -> V,
8383
reloadCompute: suspend (K, V) -> V,
8484
): LoadingCache<K, V> {
@@ -100,7 +100,7 @@ fun <K, V> Caffeine<Any, Any>.asLoadingCache(
100100
*
101101
* The compute functions will execute on the given [scope].
102102
*/
103-
fun <K, V> Caffeine<Any, Any>.asLoadingCache(
103+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asLoadingCache(
104104
scope: CoroutineScope,
105105
compute: suspend (K) -> V,
106106
reloadCompute: suspend (K, V) -> V,
@@ -125,7 +125,7 @@ fun <K, V> Caffeine<Any, Any>.asLoadingCache(
125125
* If the suspendable computation throws or computes a null value then the
126126
* entry will be automatically removed.
127127
*/
128-
fun <K, V> Caffeine<Any, Any>.asBulkLoadingCache(compute: suspend (Set<K>) -> Map<K, V>): LoadingCache<K, V> {
128+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asBulkLoadingCache(compute: suspend (Set<K>) -> Map<K, V>): LoadingCache<K, V> {
129129
val scope = CoroutineScope(Dispatchers.IO + CoroutineName("Aedile-AsyncLoadingCache-Scope") + SupervisorJob())
130130
return asBulkLoadingCache(scope, compute)
131131
}
@@ -141,7 +141,7 @@ fun <K, V> Caffeine<Any, Any>.asBulkLoadingCache(compute: suspend (Set<K>) -> Ma
141141
*
142142
* The compute function will execute on the given [scope].
143143
*/
144-
fun <K, V> Caffeine<Any, Any>.asBulkLoadingCache(
144+
fun <K : Any?, V : Any?> Caffeine<in K, in V>.asBulkLoadingCache(
145145
scope: CoroutineScope,
146146
compute: suspend (Set<K>) -> Map<K, V>
147147
): LoadingCache<K, V> {

aedile-core/src/test/kotlin/com/sksamuel/aedile/core/AsLoadingCacheTest.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.sksamuel.aedile.core
22

33
import com.github.benmanes.caffeine.cache.Caffeine
4+
import com.github.benmanes.caffeine.cache.Expiry
45
import io.kotest.assertions.throwables.shouldNotThrowAny
56
import io.kotest.assertions.throwables.shouldThrow
67
import io.kotest.core.spec.style.FunSpec
@@ -9,6 +10,7 @@ import io.kotest.matchers.shouldBe
910
import kotlinx.coroutines.delay
1011
import kotlinx.coroutines.supervisorScope
1112
import kotlinx.coroutines.yield
13+
import org.checkerframework.checker.index.qual.NonNegative
1214
import java.util.concurrent.atomic.AtomicInteger
1315
import kotlin.time.Duration.Companion.milliseconds
1416

@@ -316,5 +318,40 @@ class AsLoadingCacheTest : FunSpec() {
316318
cache.contains("wibble") shouldBe true
317319
cache.contains("bubble") shouldBe false
318320
}
321+
322+
test("check invariants on expire after") {
323+
val loggerExpiry = object : Expiry<Int, String> {
324+
override fun expireAfterRead(
325+
key: Int?,
326+
value: String?,
327+
currentTime: Long,
328+
currentDuration: @NonNegative Long
329+
): Long {
330+
return 0
331+
}
332+
333+
override fun expireAfterCreate(key: Int?, value: String?, currentTime: Long): Long {
334+
return 0
335+
}
336+
337+
override fun expireAfterUpdate(
338+
key: Int?,
339+
value: String?,
340+
currentTime: Long,
341+
currentDuration: @NonNegative Long
342+
): Long {
343+
return 0
344+
}
345+
}
346+
347+
Caffeine.newBuilder()
348+
.maximumSize(2000)
349+
.initialCapacity(500)
350+
.expireAfter(loggerExpiry)
351+
.asLoadingCache<Int, String> {
352+
delay(1)
353+
"bar"
354+
}
355+
}
319356
}
320357
}

0 commit comments

Comments
 (0)