diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b76eb62f9c..5c20967ee59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.20.3 +* `Repos`: + * `Cache`: + * Fixes in locks of caches + ## 0.20.2 * All main repos uses `SmartRWLocker` 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 22b34ffec54..50d1918d07c 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 @@ -28,9 +28,18 @@ open class FullReadCRUDCacheRepo( kvCache.action().onPresented { return it } } return parentRepo.actionElse().also { - locker.withWriteLock { kvCache.actualize(it) } + kvCache.actualize(it) } } + protected suspend inline fun doOrTakeAndActualizeWithWriteLock( + action: KeyValueRepo.() -> Optional, + actionElse: ReadCRUDRepo.() -> T, + actualize: KeyValueRepo.(T) -> Unit + ): T = doOrTakeAndActualize( + action = action, + actionElse = actionElse, + actualize = { locker.withWriteLock { actualize(it) } } + ) protected open suspend fun actualizeAll() { locker.withWriteLock { kvCache.actualizeAll(parentRepo) } @@ -54,22 +63,22 @@ open class FullReadCRUDCacheRepo( { if (it != 0L) actualizeAll() } ) - override suspend fun contains(id: IdType): Boolean = doOrTakeAndActualize( + override suspend fun contains(id: IdType): Boolean = doOrTakeAndActualizeWithWriteLock( { contains(id).takeIf { it }.optionalOrAbsentIfNull }, { contains(id) }, - { if (it) parentRepo.getById(id) ?.let { set(id, it) } } + { if (it) parentRepo.getById(id) ?.let { kvCache.set(id, it) } } ) - override suspend fun getAll(): Map = doOrTakeAndActualize( + override suspend fun getAll(): Map = doOrTakeAndActualizeWithWriteLock( { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll() }, { kvCache.actualizeAll(clear = true) { it } } ) - override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualize( + override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( { get(id) ?.optional ?: Optional.absent() }, { getById(id) }, - { it ?.let { set(idGetter(it), it) } } + { it ?.let { kvCache.set(idGetter(it), it) } } ) override suspend fun invalidate() { 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 898bab97e09..b8a53ab9457 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 @@ -28,9 +28,18 @@ open class FullReadKeyValueCacheRepo( kvCache.action().onPresented { return it } } return parentRepo.actionElse().also { - locker.withWriteLock { kvCache.actualize(it) } + kvCache.actualize(it) } } + protected suspend inline fun doOrTakeAndActualizeWithWriteLock( + action: KeyValueRepo.() -> Optional, + actionElse: ReadKeyValueRepo.() -> T, + actualize: KeyValueRepo.(T) -> Unit + ): T = doOrTakeAndActualize( + action = action, + actionElse = actionElse, + actualize = { locker.withWriteLock { actualize(it) } } + ) protected open suspend fun actualizeAll() { locker.withWriteLock { kvCache.clear() @@ -38,10 +47,10 @@ open class FullReadKeyValueCacheRepo( } } - override suspend fun get(k: Key): Value? = doOrTakeAndActualize( + override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( { get(k) ?.optional ?: Optional.absent() }, { get(k) }, - { set(k, it ?: return@doOrTakeAndActualize) } + { kvCache.set(k, it ?: return@doOrTakeAndActualizeWithWriteLock) } ) override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult = doOrTakeAndActualize( @@ -56,13 +65,13 @@ open class FullReadKeyValueCacheRepo( { if (it != 0L) actualizeAll() } ) - override suspend fun contains(key: Key): Boolean = doOrTakeAndActualize( + override suspend fun contains(key: Key): Boolean = doOrTakeAndActualizeWithWriteLock( { contains(key).takeIf { it }.optionalOrAbsentIfNull }, { contains(key) }, { if (it) parentRepo.get(key) ?.also { kvCache.set(key, it) } } ) - override suspend fun getAll(): Map = doOrTakeAndActualize( + override suspend fun getAll(): Map = doOrTakeAndActualizeWithWriteLock( { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, { getAll() }, { kvCache.actualizeAll(clear = true) { it } } 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 5e1ff38e235..e139256d539 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 @@ -27,9 +27,18 @@ open class FullReadKeyValuesCacheRepo( kvCache.action().onPresented { return it } } return parentRepo.actionElse().also { - locker.withWriteLock { kvCache.actualize(it) } + kvCache.actualize(it) } } + protected suspend inline fun doOrTakeAndActualizeWithWriteLock( + action: KeyValueRepo>.() -> Optional, + actionElse: ReadKeyValuesRepo.() -> T, + actualize: KeyValueRepo>.(T) -> Unit + ): T = doOrTakeAndActualize( + action = action, + actionElse = actionElse, + actualize = { locker.withWriteLock { actualize(it) } } + ) protected open suspend fun actualizeKey(k: Key) { locker.withWriteLock {