From 23bcb26a588033b355ddde2ae069dffc39ed6c97 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 30 Jun 2022 02:44:44 +0600 Subject: [PATCH] complete improvements in caches --- CHANGELOG.md | 4 +- .../micro_utils/repos/cache/CRUDCacheRepo.kt | 19 ++++++- .../repos/cache/KeyValueCacheRepo.kt | 9 ++++ .../repos/cache/KeyValuesCacheRepo.kt | 9 ++++ .../repos/cache/cache/FullKVCache.kt | 4 +- .../micro_utils/repos/cache/cache/KVCache.kt | 5 +- .../repos/cache/cache/SimpleFullKVCache.kt | 4 ++ .../repos/cache/cache/SimpleKVCache.kt | 5 ++ .../repos/cache/full/FullCRUDCacheRepo.kt | 21 ++++++-- .../repos/cache/full/FullKeyValueCacheRepo.kt | 14 +++++ .../cache/full/FullKeyValuesCacheRepo.kt | 54 ++++++++++++++----- 11 files changed, 127 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2846dd6e09f..ca0d593e9fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ * `Cache`: * `KVCache` has been replaced to the package `dev.inmo.micro_utils.repos.cache` * `SimpleKVCache` has been replaced to the package `dev.inmo.micro_utils.repos.cache` - * New `KVCache` - `UnlimitedKVCache` + * New `KVCache` subtype - `FullKVCache` + * Add `Full*` variants of standard repos + * Add `cached`/`caching` (for write repos) extensions for all standard types of repos ## 0.11.9 diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CRUDCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CRUDCacheRepo.kt index d7d3fba658e..c4facb233f5 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CRUDCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CRUDCacheRepo.kt @@ -18,8 +18,13 @@ open class ReadCRUDCacheRepo( override suspend fun contains(id: IdType): Boolean = kvCache.contains(id) || parentRepo.contains(id) } +fun ReadCRUDRepo.cached( + kvCache: KVCache, + idGetter: (ObjectType) -> IdType +) = ReadCRUDCacheRepo(this, kvCache, idGetter) + open class WriteCRUDCacheRepo( - protected open val parentRepo: CRUDRepo, + protected open val parentRepo: WriteCRUDRepo, protected open val kvCache: KVCache, protected open val scope: CoroutineScope = CoroutineScope(Dispatchers.Default), protected open val idGetter: (ObjectType) -> IdType @@ -61,6 +66,12 @@ open class WriteCRUDCacheRepo( } } +fun WriteCRUDRepo.caching( + kvCache: KVCache, + scope: CoroutineScope, + idGetter: (ObjectType) -> IdType +) = WriteCRUDCacheRepo(this, kvCache, scope, idGetter) + open class CRUDCacheRepo( override val parentRepo: CRUDRepo, @@ -79,3 +90,9 @@ open class CRUDCacheRepo( idGetter ), CRUDRepo + +fun CRUDRepo.cached( + kvCache: KVCache, + scope: CoroutineScope, + idGetter: (ObjectType) -> IdType +) = CRUDCacheRepo(this, kvCache, scope, idGetter) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValueCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValueCacheRepo.kt index 6123cd2b7ce..3e2265e4466 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValueCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValueCacheRepo.kt @@ -16,6 +16,10 @@ open class ReadKeyValueCacheRepo( override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key) } +fun ReadKeyValueRepo.cached( + kvCache: KVCache +) = ReadKeyValueCacheRepo(this, kvCache) + open class KeyValueCacheRepo( parentRepo: KeyValueRepo, kvCache: KVCache, @@ -24,3 +28,8 @@ open class KeyValueCacheRepo( protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope) protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope) } + +fun KeyValueRepo.cached( + kvCache: KVCache, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) = KeyValueCacheRepo(this, kvCache, scope) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValuesCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValuesCacheRepo.kt index e036b41b7ce..afe2d202d8c 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValuesCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValuesCacheRepo.kt @@ -30,6 +30,10 @@ open class ReadKeyValuesCacheRepo( override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k) } +fun ReadKeyValuesRepo.cached( + kvCache: KVCache> +) = ReadKeyValuesCacheRepo(this, kvCache) + open class KeyValuesCacheRepo( parentRepo: KeyValuesRepo, kvCache: KVCache>, @@ -39,3 +43,8 @@ open class KeyValuesCacheRepo( protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.minus(it.second) ?: return@onEach) }.launchIn(scope) protected val onDataClearedJob = parentRepo.onDataCleared.onEach { kvCache.unset(it) }.launchIn(scope) } + +fun KeyValuesRepo.cached( + kvCache: KVCache>, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) = KeyValuesCacheRepo(this, kvCache, scope) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt index 73fec60cad8..961e687b260 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt @@ -3,4 +3,6 @@ package dev.inmo.micro_utils.repos.cache.cache /** * This interface declares that current type of [KVCache] will contains all the data all the time of its life */ -interface FullKVCache : KVCache +interface FullKVCache : KVCache { + companion object +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt index 04a4f2320f7..4ab2c7563bc 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt @@ -2,5 +2,6 @@ package dev.inmo.micro_utils.repos.cache.cache import dev.inmo.micro_utils.repos.* -interface KVCache : KeyValueRepo - +interface KVCache : KeyValueRepo { + companion object +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt index e15a860c27d..a5ee4639b3d 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt @@ -22,3 +22,7 @@ open class SimpleFullKVCache( } } } + +inline fun FullKVCache( + kvParent: KeyValueRepo = MapKeyValueRepo() +) = SimpleFullKVCache(kvParent) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleKVCache.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleKVCache.kt index 3469e4ccf5c..56fe1091383 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleKVCache.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleKVCache.kt @@ -35,3 +35,8 @@ open class SimpleKVCache( syncMutex.withLock { makeUnset(toUnset) } } } + +inline fun KVCache( + cachedValuesCount: Int, + kvParent: KeyValueRepo = MapKeyValueRepo() +) = SimpleKVCache(cachedValuesCount, kvParent) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt index 7a8a07a117b..f5a76e06b1d 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt @@ -7,10 +7,10 @@ import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.* import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.cache.KVCache import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers - open class FullReadCRUDCacheRepo( protected open val parentRepo: ReadCRUDRepo, protected open val kvCache: FullKVCache, @@ -58,11 +58,18 @@ open class FullReadCRUDCacheRepo( { if (it) parentRepo.getById(id) ?.let { set(id, it) } } ) - override suspend fun getById(id: IdType): ObjectType? { - TODO("Not yet implemented") - } + override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualize( + { get(id) ?.optional ?: Optional.absent() }, + { getById(id) }, + { it ?.let { set(idGetter(it), it) } } + ) } +fun ReadCRUDRepo.cached( + kvCache: FullKVCache, + idGetter: (ObjectType) -> IdType +) = FullReadCRUDCacheRepo(this, kvCache, idGetter) + open class FullCRUDCacheRepo( override val parentRepo: CRUDRepo, kvCache: FullKVCache, @@ -80,3 +87,9 @@ open class FullCRUDCacheRepo( idGetter ), CRUDRepo + +fun CRUDRepo.cached( + kvCache: FullKVCache, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), + idGetter: (ObjectType) -> IdType +) = FullCRUDCacheRepo(this, kvCache, scope, idGetter) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt index 5bdb8746ebe..6e428846c25 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt @@ -70,6 +70,10 @@ open class FullReadKeyValueCacheRepo( ) } +fun ReadKeyValueRepo.cached( + kvCache: FullKVCache +) = FullReadKeyValueCacheRepo(this, kvCache) + open class FullWriteKeyValueCacheRepo( protected open val parentRepo: WriteKeyValueRepo, protected open val kvCache: FullKVCache, @@ -79,6 +83,11 @@ open class FullWriteKeyValueCacheRepo( protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope) } +fun WriteKeyValueRepo.caching( + kvCache: FullKVCache, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) = FullWriteKeyValueCacheRepo(this, kvCache, scope) + open class FullKeyValueCacheRepo( parentRepo: KeyValueRepo, kvCache: FullKVCache, @@ -88,3 +97,8 @@ open class FullKeyValueCacheRepo( ReadKeyValueRepo by FullReadKeyValueCacheRepo(parentRepo, kvCache) { override suspend fun unsetWithValues(toUnset: List) = parentRepo.unsetWithValues(toUnset) } + +fun KeyValueRepo.cached( + kvCache: FullKVCache, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) = FullKeyValueCacheRepo(this, kvCache, scope) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt index 311e4d40f1c..014cde674e4 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt @@ -104,21 +104,51 @@ open class FullReadKeyValuesCacheRepo( } +fun ReadKeyValuesRepo.cached( + kvCache: FullKVCache> +) = FullReadKeyValuesCacheRepo(this, kvCache) + open class FullWriteKeyValuesCacheRepo( - protected open val parentRepo: WriteKeyValueRepo, - protected open val kvCache: FullKVCache, + protected open val parentRepo: WriteKeyValuesRepo, + protected open val kvCache: FullKVCache>, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) -) : WriteKeyValueRepo by parentRepo { - protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope) - protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope) +) : WriteKeyValuesRepo by parentRepo { + protected val onNewJob = parentRepo.onNewValue.onEach { + kvCache.set( + it.first, + kvCache.get(it.first) ?.plus(it.second) ?: listOf(it.second) + ) + }.launchIn(scope) + protected val onRemoveJob = parentRepo.onValueRemoved.onEach { + kvCache.set( + it.first, + kvCache.get(it.first) ?.minus(it.second) ?: return@onEach + ) + }.launchIn(scope) } -open class FullKeyValuesCacheRepo( - parentRepo: KeyValueRepo, - kvCache: FullKVCache, +fun WriteKeyValuesRepo.caching( + kvCache: FullKVCache>, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) -) : FullWriteKeyValueCacheRepo(parentRepo, kvCache, scope), - KeyValueRepo, - ReadKeyValueRepo by FullReadKeyValueCacheRepo(parentRepo, kvCache) { - override suspend fun unsetWithValues(toUnset: List) = parentRepo.unsetWithValues(toUnset) +) = FullWriteKeyValuesCacheRepo(this, kvCache, scope) + +open class FullKeyValuesCacheRepo( + parentRepo: KeyValuesRepo, + kvCache: FullKVCache>, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) : FullWriteKeyValuesCacheRepo(parentRepo, kvCache, scope), + KeyValuesRepo, + ReadKeyValuesRepo by FullReadKeyValuesCacheRepo(parentRepo, kvCache) { + override suspend fun clearWithValue(v: Value) { + doAllWithCurrentPaging { + keys(v, it).also { + remove(it.results.associateWith { listOf(v) }) + } + } + } } + +fun KeyValuesRepo.caching( + kvCache: FullKVCache>, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default) +) = FullKeyValuesCacheRepo(this, kvCache, scope)