Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 0 additions & 97 deletions aedile-core/src/main/kotlin/com/sksamuel/aedile/core/Builder.kt

This file was deleted.

33 changes: 15 additions & 18 deletions aedile-core/src/main/kotlin/com/sksamuel/aedile/core/Cache.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executor
import kotlin.coroutines.coroutineContext

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

Expand All @@ -24,7 +22,7 @@ class Cache<K, V>(
}

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

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

/**
* Returns the value associated with key in this cache, obtaining that value from the
* Returns the value associated with a key in this cache, getting that value from the
* [compute] function if necessary. This function will suspend while the compute method
* is executed.
*
Expand All @@ -55,10 +53,10 @@ class Cache<K, V>(
*
*/
suspend fun get(key: K, compute: suspend (K) -> V): V {
val scope = scope()
val scope = CoroutineScope(coroutineContext)
var error: Throwable? = null
val value = cache.get(key) { k, _ ->
scope.async {
val asCompletableFuture = scope.async {
// if compute throws, then it will cause the parent coroutine to be cancelled as well
// we don't want that, as want to throw the exception back to the caller.
// so we must capture it and throw it manually
Expand All @@ -69,25 +67,28 @@ class Cache<K, V>(
null
}
}.asCompletableFuture()
asCompletableFuture.thenApply { it ?: throw error ?: NullPointerException() }
}.await()
error?.let { throw it }
return value
}

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

Expand Down Expand Up @@ -115,10 +116,10 @@ class Cache<K, V>(
* If the suspendable computation throws, the entry will be automatically removed.
*
* @param key the key to associate the computed value with
* @param compute the suspendable function that generate the value.
* @param compute the suspendable function that generates the value.
*/
suspend fun put(key: K, compute: suspend () -> V) {
val scope = scope()
val scope = CoroutineScope(coroutineContext)
cache.put(key, scope.async { compute() }.asCompletableFuture())
}

Expand All @@ -140,7 +141,7 @@ class Cache<K, V>(
}

suspend fun getAll(keys: Collection<K>, compute: suspend (Collection<K>) -> Map<K, V>): Map<K, V> {
val scope = scope()
val scope = CoroutineScope(coroutineContext)
var error: Throwable? = null
val value = cache.getAll(keys) { ks: Set<K>, _: Executor ->
scope.async {
Expand Down Expand Up @@ -176,8 +177,4 @@ class Cache<K, V>(
fun invalidateAll() {
cache.synchronous().invalidateAll()
}

private suspend fun scope(): CoroutineScope {
return if (useCallingContext) CoroutineScope(coroutineContext) else defaultScope
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import kotlinx.coroutines.future.await
import java.util.concurrent.CompletableFuture
import kotlin.coroutines.coroutineContext

class LoadingCache<K, V>(
class LoadingCache<K : Any, V>(
private val defaultScope: CoroutineScope,
private val useCallingContext: Boolean,
private val cache: AsyncLoadingCache<K, V>
Expand Down Expand Up @@ -73,9 +73,9 @@ class LoadingCache<K, V>(
}

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

/**
* Returns the value associated with key in this cache, obtaining that value from the
* Returns the value associated with a key in this cache, getting that value from the
* [compute] function if necessary. This function will suspend while the compute method
* is executed. If the suspendable computation throws, the exception will be propagated to the caller.
*
Expand Down Expand Up @@ -160,7 +160,7 @@ class LoadingCache<K, V>(
/**
* Discards the given key in the cache.
* Will block until completed.
* Behavior of the entry if currently being loaded is undefined.
* The behavior of the entry if currently being loaded is undefined.
*/
fun invalidate(key: K) {
cache.synchronous().invalidate(key)
Expand All @@ -169,14 +169,14 @@ class LoadingCache<K, V>(
/**
* Discards all entries in the cache.
* Will block until completed.
* Behavior of entries currently being loaded is undefined.
* The behavior of entries currently being loaded is undefined.
*/
fun invalidateAll() {
cache.synchronous().invalidateAll()
}

/**
* Loads a new value for the key, asynchronously. While the new value is loading the
* 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].
Expand All @@ -186,12 +186,12 @@ class LoadingCache<K, V>(
}

/**
* Loads a new value for each key, asynchronously. While the new value is loading the
* 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].
*/
suspend fun refreshAll(keys: Collection<K>): Map<K?, V?> {
suspend fun refreshAll(keys: Collection<K>): Map<K, V> {
return cache.synchronous().refreshAll(keys).await()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sksamuel.aedile.core

import kotlinx.coroutines.Deferred
import kotlin.time.Duration

fun interface Scheduler {
fun schedule(command: () -> Unit, duration: Duration): Deferred<Unit>
}


Loading