improve of actualize all

This commit is contained in:
InsanusMokrassar 2024-02-21 00:05:57 +06:00
parent 15a2eee141
commit ccc0002eb2
11 changed files with 184 additions and 59 deletions

View File

@ -2,6 +2,11 @@
## 0.20.36 ## 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 ## 0.20.35
* `Versions`: * `Versions`:

View File

@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.withReadAcquire
import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.cache.cache.KVCache 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 dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -29,7 +30,7 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>(
kvCache.getAll() kvCache.getAll()
}.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also { }.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also {
locker.withWriteLock { locker.withWriteLock {
kvCache.actualizeAll(true) { it } kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it }
} }
} }
} }
@ -148,7 +149,9 @@ open class CRUDCacheRepo<ObjectType, IdType, InputValueType>(
locker, locker,
idGetter idGetter
), ),
CRUDRepo<ObjectType, IdType, InputValueType> CRUDRepo<ObjectType, IdType, InputValueType> {
override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
}
fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached( fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached(
kvCache: KVCache<IdType, ObjectType>, kvCache: KVCache<IdType, ObjectType>,

View File

@ -1,5 +1,11 @@
package dev.inmo.micro_utils.repos.cache 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() suspend fun invalidate()
} }
typealias CacheRepo = InvalidatableRepo

View File

@ -6,6 +6,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.cache.cache.KVCache 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -48,9 +49,7 @@ open class ReadKeyValueCacheRepo<Key,Value>(
} }
} }
override suspend fun invalidate() = locker.withWriteLock { override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
kvCache.clear()
}
} }
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached( fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
@ -75,10 +74,6 @@ open class KeyValueCacheRepo<Key,Value>(
} }
}.launchIn(scope) }.launchIn(scope)
override suspend fun invalidate() = locker.withWriteLock {
kvCache.clear()
}
override suspend fun clear() { override suspend fun clear() {
parentRepo.clear() parentRepo.clear()
locker.withWriteLock { locker.withWriteLock {

View File

@ -7,6 +7,7 @@ import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.pagination.utils.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.cache.cache.KVCache 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -47,9 +48,7 @@ open class ReadKeyValuesCacheRepo<Key,Value>(
kvCache.contains(k) kvCache.contains(k)
} || parentRepo.contains(k) } || parentRepo.contains(k)
override suspend fun invalidate() = locker.withWriteLock { override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
kvCache.clear()
}
} }
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached( fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
@ -84,10 +83,6 @@ open class KeyValuesCacheRepo<Key,Value>(
kvCache.unset(it) kvCache.unset(it)
} }
}.launchIn(scope) }.launchIn(scope)
override suspend fun invalidate() = locker.withWriteLock {
kvCache.clear()
}
} }
fun <Key, Value> KeyValuesRepo<Key, Value>.cached( fun <Key, Value> KeyValuesRepo<Key, Value>.cached(

View File

@ -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.fallback.ActionWrapper
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo 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 dev.inmo.micro_utils.repos.set
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -56,7 +57,7 @@ open class AutoRecacheReadCRUDRepo<RegisteredObject, Id>(
override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap {
originalRepo.getAll() originalRepo.getAll()
}.onSuccess { }.onSuccess {
kvCache.actualizeAll(clear = true) { it } kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it }
}.getOrElse { }.getOrElse {
kvCache.getAll() kvCache.getAll()
} }

View File

@ -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.fallback.ActionWrapper
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo 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 dev.inmo.micro_utils.repos.set
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -56,7 +57,7 @@ open class AutoRecacheReadKeyValueRepo<Id, RegisteredObject>(
override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap {
originalRepo.getAll() originalRepo.getAll()
}.onSuccess { }.onSuccess {
kvCache.actualizeAll(clear = true) { it } kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it }
}.getOrElse { }.getOrElse {
kvCache.getAll() kvCache.getAll()
} }

View File

@ -9,6 +9,7 @@ import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.cache.* 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 dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -42,7 +43,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>(
) )
protected open suspend fun actualizeAll() { protected open suspend fun actualizeAll() {
locker.withWriteLock { kvCache.actualizeAll(parentRepo) } kvCache.actualizeAll(parentRepo, locker = locker)
} }
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize( override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize(
@ -72,7 +73,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>(
override suspend fun getAll(): Map<IdType, ObjectType> = doOrTakeAndActualizeWithWriteLock( override suspend fun getAll(): Map<IdType, ObjectType> = doOrTakeAndActualizeWithWriteLock(
{ getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull },
{ getAll() }, { getAll() },
{ kvCache.actualizeAll(clear = true) { it } } { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } }
) )
override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock(

View File

@ -8,8 +8,8 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* 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.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.pagination.getAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -41,10 +41,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>(
actualize = { locker.withWriteLock { actualize(it) } } actualize = { locker.withWriteLock { actualize(it) } }
) )
protected open suspend fun actualizeAll() { protected open suspend fun actualizeAll() {
locker.withWriteLock { kvCache.actualizeAll(parentRepo, locker)
kvCache.clear()
kvCache.set(parentRepo.getAll())
}
} }
override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock(
@ -74,7 +71,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>(
override suspend fun getAll(): Map<Key, Value> = doOrTakeAndActualizeWithWriteLock( override suspend fun getAll(): Map<Key, Value> = doOrTakeAndActualizeWithWriteLock(
{ getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull },
{ getAll() }, { getAll() },
{ kvCache.actualizeAll(clear = true) { it } } { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } }
) )
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize( override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize(
@ -150,9 +147,7 @@ open class FullKeyValueCacheRepo<Key,Value>(
override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset) override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset)
override suspend fun invalidate() { override suspend fun invalidate() {
locker.withWriteLock { kvCache.actualizeAll(parentRepo, locker)
kvCache.actualizeAll(parentRepo)
}
} }
override suspend fun clear() { override suspend fun clear() {

View File

@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.pagination.utils.*
import dev.inmo.micro_utils.repos.* 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.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -41,15 +42,13 @@ open class FullReadKeyValuesCacheRepo<Key,Value>(
) )
protected open suspend fun actualizeKey(k: Key) { protected open suspend fun actualizeKey(k: Key) {
locker.withWriteLock { kvCache.actualizeAll(locker = locker, clearMode = ActualizeAllClearMode.Never) {
kvCache.set(k, parentRepo.getAll(k)) mapOf(k to parentRepo.getAll(k))
} }
} }
protected open suspend fun actualizeAll() { protected open suspend fun actualizeAll() {
locker.withWriteLock { kvCache.actualizeAll(parentRepo, locker = locker)
kvCache.actualizeAll(parentRepo)
}
} }
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> { override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
@ -187,9 +186,7 @@ open class FullKeyValuesCacheRepo<Key,Value>(
} }
override suspend fun invalidate() { override suspend fun invalidate() {
locker.withWriteLock { kvCache.actualizeAll(parentRepo, locker = locker)
kvCache.actualizeAll(parentRepo)
}
} }
override suspend fun set(toSet: Map<Key, List<Value>>) { override suspend fun set(toSet: Map<Key, List<Value>>) {

View File

@ -1,43 +1,169 @@
package dev.inmo.micro_utils.repos.cache.util 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 dev.inmo.micro_utils.repos.*
import kotlinx.serialization.Serializable
import kotlin.js.JsName
import kotlin.jvm.JvmName
suspend inline fun <K, V> KeyValueRepo<K, V>.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 <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad(
getAll: () -> Map<K, V> getAll: () -> Map<K, V>
) { ) {
set( clear()
getAll().also { val newData = getAll()
if (clear) { set(newData)
}
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet(
getAll: () -> Map<K, V>
) {
val newData = getAll()
clear()
set(newData)
}
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear(
getAll: () -> Map<K, V>
) {
val newData = getAll()
set(newData)
}
@JvmName("actualizeAllWithClearBeforeLoadWithLocker")
@JsName("actualizeAllWithClearBeforeLoadWithLocker")
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad(
locker: SmartRWLocker,
getAll: () -> Map<K, V>
) {
locker.withWriteLock {
clear() clear()
} }
val newData = getAll()
locker.withWriteLock {
set(newData)
} }
) }
@JvmName("actualizeAllWithClearBeforeSetWithLocker")
@JsName("actualizeAllWithClearBeforeSetWithLocker")
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet(
locker: SmartRWLocker,
getAll: () -> Map<K, V>
) {
val newData = getAll()
locker.withWriteLock {
clear()
set(newData)
}
}
@JvmName("actualizeAllWithoutClearWithLocker")
@JsName("actualizeAllWithoutClearWithLocker")
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear(
locker: SmartRWLocker,
getAll: () -> Map<K, V>
) {
val newData = getAll()
locker.withWriteLock {
set(newData)
}
}
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad(
locker: SmartRWLocker? = null,
getAll: () -> Map<K, V>
) {
locker ?.let {
actualizeAllWithClearBeforeLoad(locker = locker, getAll)
} ?: actualizeAllWithClearBeforeLoad(getAll)
}
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet(
locker: SmartRWLocker? = null,
getAll: () -> Map<K, V>
) {
locker ?.let {
actualizeAllWithClearBeforeSet(locker = locker, getAll)
} ?: actualizeAllWithClearBeforeSet(getAll)
}
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear(
locker: SmartRWLocker? = null,
getAll: () -> Map<K, V>
) {
locker ?.let {
actualizeAllWithoutClear(locker = locker, getAll)
} ?: actualizeAllWithoutClear(getAll)
} }
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll(
repo: ReadKeyValueRepo<K, V>, locker: SmartRWLocker? = null,
clear: Boolean = true, clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet,
getAll: () -> Map<K, V>
) { ) {
actualizeAll(clear) { when (clearMode) {
repo.getAll() 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 <K, V> KeyValueRepo<K, V>.actualizeAll(
parentRepo: ReadKeyValueRepo<K, V>,
locker: SmartRWLocker? = null,
clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet,
) {
actualizeAll(locker, clearMode) {
parentRepo.getAll()
} }
} }
suspend inline fun <K, V> KeyValueRepo<K, List<V>>.actualizeAll( suspend inline fun <K, V> KeyValueRepo<K, List<V>>.actualizeAll(
repo: ReadKeyValuesRepo<K, V>, parentRepo: ReadKeyValuesRepo<K, V>,
clear: Boolean = true, locker: SmartRWLocker? = null,
clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet,
) { ) {
actualizeAll(clear) { actualizeAll(locker, clearMode) {
repo.getAll() parentRepo.getAll()
} }
} }
suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll(
repo: ReadCRUDRepo<V, K>, parentRepo: ReadCRUDRepo<V, K>,
clear: Boolean = true, locker: SmartRWLocker? = null,
clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet,
) { ) {
actualizeAll(clear) { actualizeAll(locker, clearMode) {
repo.getAll() parentRepo.getAll()
} }
} }