From ccc0002eb258feb01396a7a29b42c677b6945971 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 21 Feb 2024 00:05:57 +0600 Subject: [PATCH] improve of actualize all --- CHANGELOG.md | 5 + .../micro_utils/repos/cache/CRUDCacheRepo.kt | 7 +- .../inmo/micro_utils/repos/cache/CacheRepo.kt | 8 +- .../repos/cache/KeyValueCacheRepo.kt | 9 +- .../repos/cache/KeyValuesCacheRepo.kt | 9 +- .../fallback/crud/AutoRecacheReadCRUDRepo.kt | 3 +- .../keyvalue/AutoRecacheReadKeyValueRepo.kt | 3 +- .../repos/cache/full/FullCRUDCacheRepo.kt | 5 +- .../repos/cache/full/FullKeyValueCacheRepo.kt | 13 +- .../cache/full/FullKeyValuesCacheRepo.kt | 13 +- .../repos/cache/util/ActualizeAll.kt | 168 +++++++++++++++--- 11 files changed, 184 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4abca82575..497db35bf9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 0.20.36 +* `Repos`: + * `Cache`: + * Improve work and functionality of `actualizeAll` and subsequent functions + * All internal repos `invalidate`/`actualizeAll` now use common `actualizeAll` functions + ## 0.20.35 * `Versions`: 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 0a58b4ceffa..b879fd0dc9c 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 @@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.cache.KVCache +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.actualizeAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -29,7 +30,7 @@ open class ReadCRUDCacheRepo( kvCache.getAll() }.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also { locker.withWriteLock { - kvCache.actualizeAll(true) { it } + kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } } } @@ -148,7 +149,9 @@ open class CRUDCacheRepo( locker, idGetter ), - CRUDRepo + CRUDRepo { + override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) +} fun CRUDRepo.cached( kvCache: KVCache, diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt index 55abb179fd6..6d683617fb0 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt @@ -1,5 +1,11 @@ package dev.inmo.micro_utils.repos.cache -interface CacheRepo { +interface InvalidatableRepo { + /** + * Invalidates its internal data. It __may__ lead to autoreload of data. In case when repo makes autoreload, + * it must do loading of data __before__ clear + */ suspend fun invalidate() } + +typealias CacheRepo = InvalidatableRepo 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 6125fcf0b5e..db336389b5a 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 @@ -6,6 +6,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.cache.KVCache +import dev.inmo.micro_utils.repos.cache.util.actualizeAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* @@ -48,9 +49,7 @@ open class ReadKeyValueCacheRepo( } } - override suspend fun invalidate() = locker.withWriteLock { - kvCache.clear() - } + override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) } fun ReadKeyValueRepo.cached( @@ -75,10 +74,6 @@ open class KeyValueCacheRepo( } }.launchIn(scope) - override suspend fun invalidate() = locker.withWriteLock { - kvCache.clear() - } - override suspend fun clear() { parentRepo.clear() locker.withWriteLock { 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 bf8857b60ab..cfdfd511dee 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 @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.cache.KVCache +import dev.inmo.micro_utils.repos.cache.util.actualizeAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* @@ -47,9 +48,7 @@ open class ReadKeyValuesCacheRepo( kvCache.contains(k) } || parentRepo.contains(k) - override suspend fun invalidate() = locker.withWriteLock { - kvCache.clear() - } + override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) } fun ReadKeyValuesRepo.cached( @@ -84,10 +83,6 @@ open class KeyValuesCacheRepo( kvCache.unset(it) } }.launchIn(scope) - - override suspend fun invalidate() = locker.withWriteLock { - kvCache.clear() - } } fun KeyValuesRepo.cached( diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt index 2a08cbe63c5..e84912ebc64 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.set import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -56,7 +57,7 @@ open class AutoRecacheReadCRUDRepo( override suspend fun getAll(): Map = actionWrapper.wrap { originalRepo.getAll() }.onSuccess { - kvCache.actualizeAll(clear = true) { it } + kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } }.getOrElse { kvCache.getAll() } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt index e8826b6fc08..71e3360a751 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.set import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -56,7 +57,7 @@ open class AutoRecacheReadKeyValueRepo( override suspend fun getAll(): Map = actionWrapper.wrap { originalRepo.getAll() }.onSuccess { - kvCache.actualizeAll(clear = true) { it } + kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } }.getOrElse { kvCache.getAll() } 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 50d1918d07c..0afab87f949 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 @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.* +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.actualizeAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -42,7 +43,7 @@ open class FullReadCRUDCacheRepo( ) protected open suspend fun actualizeAll() { - locker.withWriteLock { kvCache.actualizeAll(parentRepo) } + kvCache.actualizeAll(parentRepo, locker = locker) } override suspend fun getByPagination(pagination: Pagination): PaginationResult = doOrTakeAndActualize( @@ -72,7 +73,7 @@ open class FullReadCRUDCacheRepo( override suspend fun getAll(): Map = doOrTakeAndActualizeWithWriteLock( { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll() }, - { kvCache.actualizeAll(clear = true) { it } } + { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } ) override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( 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 3eeb3627f70..86140ebe27f 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 @@ -8,8 +8,8 @@ import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.repos.* +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.actualizeAll -import dev.inmo.micro_utils.repos.pagination.getAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* @@ -41,10 +41,7 @@ open class FullReadKeyValueCacheRepo( actualize = { locker.withWriteLock { actualize(it) } } ) protected open suspend fun actualizeAll() { - locker.withWriteLock { - kvCache.clear() - kvCache.set(parentRepo.getAll()) - } + kvCache.actualizeAll(parentRepo, locker) } override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( @@ -74,7 +71,7 @@ open class FullReadKeyValueCacheRepo( override suspend fun getAll(): Map = doOrTakeAndActualizeWithWriteLock( { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll() }, - { kvCache.actualizeAll(clear = true) { it } } + { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } ) override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult = doOrTakeAndActualize( @@ -150,9 +147,7 @@ open class FullKeyValueCacheRepo( override suspend fun unsetWithValues(toUnset: List) = parentRepo.unsetWithValues(toUnset) override suspend fun invalidate() { - locker.withWriteLock { - kvCache.actualizeAll(parentRepo) - } + kvCache.actualizeAll(parentRepo, locker) } override suspend fun clear() { 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 2aae6cfc227..80844c4d097 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 @@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.repos.* +import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.actualizeAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -41,15 +42,13 @@ open class FullReadKeyValuesCacheRepo( ) protected open suspend fun actualizeKey(k: Key) { - locker.withWriteLock { - kvCache.set(k, parentRepo.getAll(k)) + kvCache.actualizeAll(locker = locker, clearMode = ActualizeAllClearMode.Never) { + mapOf(k to parentRepo.getAll(k)) } } protected open suspend fun actualizeAll() { - locker.withWriteLock { - kvCache.actualizeAll(parentRepo) - } + kvCache.actualizeAll(parentRepo, locker = locker) } override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult { @@ -187,9 +186,7 @@ open class FullKeyValuesCacheRepo( } override suspend fun invalidate() { - locker.withWriteLock { - kvCache.actualizeAll(parentRepo) - } + kvCache.actualizeAll(parentRepo, locker = locker) } override suspend fun set(toSet: Map>) { diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt index 4ae058eb643..f8babc729fa 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt @@ -1,43 +1,169 @@ package dev.inmo.micro_utils.repos.cache.util +import dev.inmo.micro_utils.coroutines.SmartRWLocker +import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.repos.* +import kotlinx.serialization.Serializable +import kotlin.js.JsName +import kotlin.jvm.JvmName -suspend inline fun KeyValueRepo.actualizeAll( - clear: Boolean = true, +/** + * `invalidate`/`actualizeAll` clearing mode. Declare when data in original repo will be cleared + */ +@Serializable +sealed interface ActualizeAllClearMode { + /** + * Instruct user of this mode to clear internal data __before load__ of external data + */ + @Serializable + data object BeforeLoad : ActualizeAllClearMode + /** + * Instruct user of this mode to clear internal data __after load__ of external data and __before set__ of internal data + */ + @Serializable + data object BeforeSet : ActualizeAllClearMode + /** + * Instruct user of this mode to never clear internal data + */ + @Serializable + data object Never : ActualizeAllClearMode +} + +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeLoad( getAll: () -> Map ) { - set( - getAll().also { - if (clear) { - clear() - } - } - ) + clear() + val newData = getAll() + set(newData) +} + +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeSet( + getAll: () -> Map +) { + val newData = getAll() + clear() + set(newData) +} + +suspend inline fun KeyValueRepo.actualizeAllWithoutClear( + getAll: () -> Map +) { + val newData = getAll() + set(newData) +} + +@JvmName("actualizeAllWithClearBeforeLoadWithLocker") +@JsName("actualizeAllWithClearBeforeLoadWithLocker") +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeLoad( + locker: SmartRWLocker, + getAll: () -> Map +) { + locker.withWriteLock { + clear() + } + + val newData = getAll() + locker.withWriteLock { + set(newData) + } +} + +@JvmName("actualizeAllWithClearBeforeSetWithLocker") +@JsName("actualizeAllWithClearBeforeSetWithLocker") +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeSet( + locker: SmartRWLocker, + getAll: () -> Map +) { + val newData = getAll() + locker.withWriteLock { + clear() + set(newData) + } +} + +@JvmName("actualizeAllWithoutClearWithLocker") +@JsName("actualizeAllWithoutClearWithLocker") +suspend inline fun KeyValueRepo.actualizeAllWithoutClear( + locker: SmartRWLocker, + getAll: () -> Map +) { + val newData = getAll() + locker.withWriteLock { + set(newData) + } +} + +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeLoad( + locker: SmartRWLocker? = null, + getAll: () -> Map +) { + locker ?.let { + actualizeAllWithClearBeforeLoad(locker = locker, getAll) + } ?: actualizeAllWithClearBeforeLoad(getAll) +} + +suspend inline fun KeyValueRepo.actualizeAllWithClearBeforeSet( + locker: SmartRWLocker? = null, + getAll: () -> Map +) { + locker ?.let { + actualizeAllWithClearBeforeSet(locker = locker, getAll) + } ?: actualizeAllWithClearBeforeSet(getAll) +} + +suspend inline fun KeyValueRepo.actualizeAllWithoutClear( + locker: SmartRWLocker? = null, + getAll: () -> Map +) { + locker ?.let { + actualizeAllWithoutClear(locker = locker, getAll) + } ?: actualizeAllWithoutClear(getAll) } suspend inline fun KeyValueRepo.actualizeAll( - repo: ReadKeyValueRepo, - clear: Boolean = true, + locker: SmartRWLocker? = null, + clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, + getAll: () -> Map ) { - actualizeAll(clear) { - repo.getAll() + when (clearMode) { + ActualizeAllClearMode.BeforeLoad -> locker ?.let { + actualizeAllWithClearBeforeLoad(locker = locker, getAll) + } ?: actualizeAllWithClearBeforeLoad(getAll) + ActualizeAllClearMode.BeforeSet -> locker ?.let { + actualizeAllWithClearBeforeSet(locker = locker, getAll) + } ?: actualizeAllWithClearBeforeSet(getAll) + ActualizeAllClearMode.Never -> locker ?.let { + actualizeAllWithoutClear(locker = locker, getAll) + } ?: actualizeAllWithoutClear(getAll) + } +} + +suspend inline fun KeyValueRepo.actualizeAll( + parentRepo: ReadKeyValueRepo, + locker: SmartRWLocker? = null, + clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, +) { + actualizeAll(locker, clearMode) { + parentRepo.getAll() } } suspend inline fun KeyValueRepo>.actualizeAll( - repo: ReadKeyValuesRepo, - clear: Boolean = true, + parentRepo: ReadKeyValuesRepo, + locker: SmartRWLocker? = null, + clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, ) { - actualizeAll(clear) { - repo.getAll() + actualizeAll(locker, clearMode) { + parentRepo.getAll() } } suspend inline fun KeyValueRepo.actualizeAll( - repo: ReadCRUDRepo, - clear: Boolean = true, + parentRepo: ReadCRUDRepo, + locker: SmartRWLocker? = null, + clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, ) { - actualizeAll(clear) { - repo.getAll() + actualizeAll(locker, clearMode) { + parentRepo.getAll() } }