MicroUtils/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/KeyValueCacheRepo.kt

90 lines
3.1 KiB
Kotlin
Raw Normal View History

2021-03-24 07:01:15 +00:00
package dev.inmo.micro_utils.repos.cache
import dev.inmo.micro_utils.coroutines.SmartRWLocker
import dev.inmo.micro_utils.coroutines.withReadAcquire
import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.*
2021-03-24 07:01:15 +00:00
import dev.inmo.micro_utils.repos.*
2022-06-29 13:31:57 +00:00
import dev.inmo.micro_utils.repos.cache.cache.KVCache
2024-02-20 18:05:57 +00:00
import dev.inmo.micro_utils.repos.cache.util.actualizeAll
2021-03-24 07:01:15 +00:00
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
open class ReadKeyValueCacheRepo<Key,Value>(
2022-06-29 17:53:49 +00:00
protected open val parentRepo: ReadKeyValueRepo<Key, Value>,
protected open val kvCache: KVCache<Key, Value>,
protected val locker: SmartRWLocker = SmartRWLocker(),
2023-01-27 08:45:31 +00:00
) : ReadKeyValueRepo<Key,Value> by parentRepo, CommonCacheRepo {
override suspend fun get(k: Key): Value? = locker.withReadAcquire {
kvCache.get(k)
} ?: parentRepo.get(k) ?.also {
locker.withWriteLock {
kvCache.set(k, it)
}
}
override suspend fun contains(key: Key): Boolean = locker.withReadAcquire {
kvCache.contains(key)
} || parentRepo.contains(key)
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
return locker.withReadAcquire {
keys(pagination, reversed).let {
it.changeResultsUnchecked(
it.results.mapNotNull {
get(it)
}
)
}
}
}
2023-01-27 08:45:31 +00:00
override suspend fun getAll(): Map<Key, Value> = locker.withReadAcquire {
kvCache.getAll()
}.takeIf {
2023-03-10 12:37:48 +00:00
it.size.toLong() == count()
} ?: parentRepo.getAll().also {
locker.withWriteLock {
kvCache.set(it)
}
2023-03-10 12:37:48 +00:00
}
2024-02-20 18:05:57 +00:00
override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
}
2022-06-29 20:44:44 +00:00
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
kvCache: KVCache<Key, Value>,
locker: SmartRWLocker = SmartRWLocker(),
) = ReadKeyValueCacheRepo(this, kvCache, locker)
2022-06-29 20:44:44 +00:00
open class KeyValueCacheRepo<Key,Value>(
2023-07-23 07:47:20 +00:00
override val parentRepo: KeyValueRepo<Key, Value>,
kvCache: KVCache<Key, Value>,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
locker: SmartRWLocker = SmartRWLocker(),
) : ReadKeyValueCacheRepo<Key,Value>(parentRepo, kvCache, locker), KeyValueRepo<Key,Value>, WriteKeyValueRepo<Key, Value> by parentRepo, CommonCacheRepo {
protected val onNewJob = parentRepo.onNewValue.onEach {
locker.withWriteLock {
kvCache.set(it.first, it.second)
}
}.launchIn(scope)
protected val onRemoveJob = parentRepo.onValueRemoved.onEach {
locker.withWriteLock {
kvCache.unset(it)
}
}.launchIn(scope)
2023-01-27 08:45:31 +00:00
2023-07-23 07:47:20 +00:00
override suspend fun clear() {
parentRepo.clear()
locker.withWriteLock {
kvCache.clear()
}
2023-07-23 07:47:20 +00:00
}
2021-03-24 07:01:15 +00:00
}
2022-06-29 20:44:44 +00:00
fun <Key, Value> KeyValueRepo<Key, Value>.cached(
kvCache: KVCache<Key, Value>,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
locker: SmartRWLocker = SmartRWLocker(),
) = KeyValueCacheRepo(this, kvCache, scope, locker)