Skip to content

Commit d50d283

Browse files
authored
Update to Caffeine 3.2 and update nullability to match jSpecify (#47)
1 parent 155c822 commit d50d283

File tree

19 files changed

+151
-894
lines changed

19 files changed

+151
-894
lines changed

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

Lines changed: 0 additions & 97 deletions
This file was deleted.

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

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import java.util.concurrent.CompletableFuture
1111
import java.util.concurrent.Executor
1212
import kotlin.coroutines.coroutineContext
1313

14-
class Cache<K, V>(
15-
@Deprecated("This should be ignored - use overloaded methods") private val defaultScope: CoroutineScope,
16-
@Deprecated("This should be ignored - use overloaded methods") private val useCallingContext: Boolean,
14+
class Cache<K : Any, V : Any>(
1715
private val cache: AsyncCache<K, V>
1816
) {
1917

@@ -24,7 +22,7 @@ class Cache<K, V>(
2422
}
2523

2624
/**
27-
* Returns the value associated with key in this cache, or null if there is no cached future for key.
25+
* Returns the value associated with a key in this cache, or null if there is no cached future for the key.
2826
* This method will suspend while the value is fetched.
2927
* For a non-suspending alternative, see [getOrNull].
3028
*/
@@ -33,15 +31,15 @@ class Cache<K, V>(
3331
}
3432

3533
/**
36-
* Returns the value associated with key in this cache or null if this cache does not
34+
* Returns the value associated with a key in this cache or null if this cache does not
3735
* contain an entry for the key. This is a non-suspendable alternative to getIfPresent(key).
3836
*/
3937
fun getOrNull(key: K): V? {
4038
return cache.synchronous().getIfPresent(key)
4139
}
4240

4341
/**
44-
* Returns the value associated with key in this cache, obtaining that value from the
42+
* Returns the value associated with a key in this cache, getting that value from the
4543
* [compute] function if necessary. This function will suspend while the compute method
4644
* is executed.
4745
*
@@ -55,10 +53,10 @@ class Cache<K, V>(
5553
*
5654
*/
5755
suspend fun get(key: K, compute: suspend (K) -> V): V {
58-
val scope = scope()
56+
val scope = CoroutineScope(coroutineContext)
5957
var error: Throwable? = null
6058
val value = cache.get(key) { k, _ ->
61-
scope.async {
59+
val asCompletableFuture = scope.async {
6260
// if compute throws, then it will cause the parent coroutine to be cancelled as well
6361
// we don't want that, as want to throw the exception back to the caller.
6462
// so we must capture it and throw it manually
@@ -69,25 +67,28 @@ class Cache<K, V>(
6967
null
7068
}
7169
}.asCompletableFuture()
70+
asCompletableFuture.thenApply { it ?: throw error ?: NullPointerException() }
7271
}.await()
7372
error?.let { throw it }
7473
return value
7574
}
7675

7776
/**
78-
* Returns the value associated with key in this cache, obtaining that value from the
77+
* Returns the value associated with a key in this cache, getting that value from the
7978
* [compute] function if necessary. This function will suspend while the compute method
8079
* is executed. If the suspendable computation throws, the exception will be propagated to the caller.
8180
*
8281
* If the specified key is not already associated with a value, attempts to compute its value asynchronously
83-
* and enters it into this cache unless null.
82+
* and enters it into this cache unless null. The entire method invocation is performed atomically, so the
83+
* function is applied at most once per key. If the asynchronous computation fails, the entry will be
84+
* automatically removed from this cache.
8485
*
8586
* @param key the key to lookup in the cache
8687
* @param compute the suspendable function to generate a value for the given key.
8788
* @return the present value, the computed value, or throws.
8889
*/
8990
suspend fun getOrNull(key: K, compute: suspend (K) -> V?): V? {
90-
val scope = scope()
91+
val scope = CoroutineScope(coroutineContext)
9192
return cache.get(key) { k, _ -> scope.async { compute(k) }.asCompletableFuture() }.await()
9293
}
9394

@@ -115,10 +116,10 @@ class Cache<K, V>(
115116
* If the suspendable computation throws, the entry will be automatically removed.
116117
*
117118
* @param key the key to associate the computed value with
118-
* @param compute the suspendable function that generate the value.
119+
* @param compute the suspendable function that generates the value.
119120
*/
120121
suspend fun put(key: K, compute: suspend () -> V) {
121-
val scope = scope()
122+
val scope = CoroutineScope(coroutineContext)
122123
cache.put(key, scope.async { compute() }.asCompletableFuture())
123124
}
124125

@@ -140,7 +141,7 @@ class Cache<K, V>(
140141
}
141142

142143
suspend fun getAll(keys: Collection<K>, compute: suspend (Collection<K>) -> Map<K, V>): Map<K, V> {
143-
val scope = scope()
144+
val scope = CoroutineScope(coroutineContext)
144145
var error: Throwable? = null
145146
val value = cache.getAll(keys) { ks: Set<K>, _: Executor ->
146147
scope.async {
@@ -176,8 +177,4 @@ class Cache<K, V>(
176177
fun invalidateAll() {
177178
cache.synchronous().invalidateAll()
178179
}
179-
180-
private suspend fun scope(): CoroutineScope {
181-
return if (useCallingContext) CoroutineScope(coroutineContext) else defaultScope
182-
}
183180
}

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

Lines changed: 0 additions & 68 deletions
This file was deleted.

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import kotlinx.coroutines.future.await
1111
import java.util.concurrent.CompletableFuture
1212
import kotlin.coroutines.coroutineContext
1313

14-
class LoadingCache<K, V>(
14+
class LoadingCache<K : Any, V>(
1515
private val defaultScope: CoroutineScope,
1616
private val useCallingContext: Boolean,
1717
private val cache: AsyncLoadingCache<K, V>
@@ -73,9 +73,9 @@ class LoadingCache<K, V>(
7373
}
7474

7575
/**
76-
* Returns the value associated with key in this cache, obtaining that value from the
76+
* Returns the value associated with a key in this cache, getting that value from the
7777
* [compute] function if necessary. This method provides a simple substitute for the conventional
78-
* "if cached, return; otherwise create, cache and return" pattern.
78+
* "if cached, return; otherwise create, cache, and return" pattern.
7979
*
8080
* The instance returned from the compute function will be stored directly into the cache.
8181
*
@@ -90,7 +90,7 @@ class LoadingCache<K, V>(
9090
}
9191

9292
/**
93-
* Returns the value associated with key in this cache, obtaining that value from the
93+
* Returns the value associated with a key in this cache, getting that value from the
9494
* [compute] function if necessary. This function will suspend while the compute method
9595
* is executed. If the suspendable computation throws, the exception will be propagated to the caller.
9696
*
@@ -160,7 +160,7 @@ class LoadingCache<K, V>(
160160
/**
161161
* Discards the given key in the cache.
162162
* Will block until completed.
163-
* Behavior of the entry if currently being loaded is undefined.
163+
* The behavior of the entry if currently being loaded is undefined.
164164
*/
165165
fun invalidate(key: K) {
166166
cache.synchronous().invalidate(key)
@@ -169,14 +169,14 @@ class LoadingCache<K, V>(
169169
/**
170170
* Discards all entries in the cache.
171171
* Will block until completed.
172-
* Behavior of entries currently being loaded is undefined.
172+
* The behavior of entries currently being loaded is undefined.
173173
*/
174174
fun invalidateAll() {
175175
cache.synchronous().invalidateAll()
176176
}
177177

178178
/**
179-
* Loads a new value for the key, asynchronously. While the new value is loading the
179+
* Loads a new value for the key, asynchronously. While the new value is loading, the
180180
* previous value (if any) will continue to be returned by get(key) unless it is evicted.
181181
*
182182
* See full docs at [com.github.benmanes.caffeine.cache.LoadingCache.refresh].
@@ -186,12 +186,12 @@ class LoadingCache<K, V>(
186186
}
187187

188188
/**
189-
* Loads a new value for each key, asynchronously. While the new value is loading the
189+
* Loads a new value for each key, asynchronously. While the new value is loading, the
190190
* previous value (if any) will continue to be returned by get(key) unless it is evicted.
191191
*
192192
* See full docs at [com.github.benmanes.caffeine.cache.LoadingCache.refreshAll].
193193
*/
194-
suspend fun refreshAll(keys: Collection<K>): Map<K?, V?> {
194+
suspend fun refreshAll(keys: Collection<K>): Map<K, V> {
195195
return cache.synchronous().refreshAll(keys).await()
196196
}
197197

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.sksamuel.aedile.core
2+
3+
import kotlinx.coroutines.Deferred
4+
import kotlin.time.Duration
5+
6+
fun interface Scheduler {
7+
fun schedule(command: () -> Unit, duration: Duration): Deferred<Unit>
8+
}
9+
10+

0 commit comments

Comments
 (0)