All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.BlockingCache.kt Maven / Gradle / Ivy

package opensavvy.cache.blocking

import kotlinx.coroutines.runBlocking
import opensavvy.cache.Cache
import opensavvy.cache.InfallibleCache
import opensavvy.state.coroutines.now
import opensavvy.state.outcome.Outcome
import opensavvy.state.outcome.value

/**
 * A blocking cache implementation.
 *
 * Unlike [asynchronous caches][Cache], this implementation doesn't allow subscribing to a value to see it change over time.
 *
 * To instantiate this class, see the [blocking] helper.
 *
 * @param Identifier An identifier representing a cached object.
 * @param Failure A cache value that represents a failure.
 * @param Value A cache value that represents a success.
 * @property upstream The underlying cache instance.
 */
class BlockingCache internal constructor(
	private val upstream: Cache,
) {

	/**
	 * Gets the value associated with [id] in the cache, at the current time.
	 *
	 * Unlike [Cache.get], this function does not allow subscribing to the value to see its changes over time.
	 */
	operator fun get(id: Identifier): Outcome = runBlocking {
		upstream[id].now()
	}

	/**
	 * Forces the cache to accept [value] as a more recent value for the given [id] than whatever it was previously storing.
	 *
	 * For more information, see [Cache.update].
	 */
	operator fun set(id: Identifier, value: Value) = runBlocking {
		upstream.update(id, value)
	}

	/**
	 * Forces the cache to accept the given [values] as more recent than their associated identifier than whatever was
	 * previously stored.
	 *
	 * For more information, see [Cache.update].
	 */
	fun update(values: Collection>) = runBlocking {
		upstream.update(values)
	}

	/**
	 * Forces the cache to accept the given [values] as more recent than their associated identifier than whatever was
	 * previously stored.
	 *
	 * For more information, see [Cache.update].
	 */
	fun update(vararg values: Pair) = update(values.asList())

	/**
	 * Tells the cache that the value it stores for [id] is out-of-date, and should be queried again the next time it is requested.
	 *
	 * For more information, see [Cache.expire].
	 */
	fun expire(id: Identifier) {
		expire(listOf(id))
	}

	/**
	 * Tells the cache that the value it stores for the given [ids] are out-of-date, and should be queried again next time they are requested.
	 *
	 * For more information, see [Cache.expire].
	 */
	fun expire(ids: Collection) = runBlocking {
		upstream.expire(ids)
	}

	/**
	 * Tells the cache that all values are out-of-date, and should be queried again the next time they are requested.
	 *
	 * For more information, see [Cache.expireAll].
	 */
	fun expireAll() = runBlocking {
		upstream.expireAll()
	}
}

/**
 * Convenience function to access a value from [infallible caches][InfallibleCache] that are blocking.
 *
 * For more information, see [BlockingCache.get] and [Cache.get].
 */
fun  BlockingCache.getValue(id: Identifier): Value =
	get(id).value

/**
 * Converts an [asynchronous cache][Cache] into a [blocking cache][BlockingCache].
 *
 * ### Example
 *
 * ```kotlin
 * // Create the coroutine context
 * val cachingJob = SupervisorJob()
 * val cachingScope = CoroutineScope(cachingJob)
 *
 * // Instantiate the cache instance
 * val cache = cache { it * 2 }
 *     .cachedInMemory(cachingJob)
 *     .expireAfter(2.minutes, cachingScope)
 *     .blocking()
 *
 * // Access the cache
 * println(cache[1]) // 2
 *
 * // Force the cache to accept another value
 * cache[1] = 3
 * println(cache[1]) // 3
 *
 * // Force the cache to forget the value, meaning a new request will be started on next access
 * cache.expire(1)
 * println(cache[1]) // 2
 *
 * // Don't forget to stop the cache workers when you're done using the cache
 * cachingJob.cancel()
 * ```
 */
fun  Cache.blocking() =
	BlockingCache(this)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy