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

69 lines
2.6 KiB
Kotlin
Raw Normal View History

2021-03-24 07:01:15 +00:00
package dev.inmo.micro_utils.repos.cache
2022-09-07 14:01:13 +00:00
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.*
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
2021-03-24 07:01:15 +00:00
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
open class ReadKeyValuesCacheRepo<Key,Value>(
2022-06-29 17:53:49 +00:00
protected open val parentRepo: ReadKeyValuesRepo<Key, Value>,
protected open val kvCache: KVCache<Key, List<Value>>
2023-01-27 08:45:31 +00:00
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CommonCacheRepo {
2021-03-24 07:01:15 +00:00
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
2022-09-07 17:47:13 +00:00
return getAll(k, reversed).paginate(
pagination
2022-09-07 14:01:13 +00:00
)
2021-03-24 07:01:15 +00:00
}
override suspend fun getAll(k: Key, reversed: Boolean): List<Value> {
return kvCache.get(k) ?.let {
2021-03-24 07:01:15 +00:00
if (reversed) it.reversed() else it
2022-09-07 14:01:13 +00:00
} ?: parentRepo.getAll(k, reversed).also {
kvCache.set(k, it)
}
2021-03-24 07:01:15 +00:00
}
2022-09-07 14:01:13 +00:00
override suspend fun contains(k: Key, v: Value): Boolean = kvCache.get(k) ?.contains(v) ?: (parentRepo.contains(k, v).also {
if (it) {
kvCache.unset(k) // clear as invalid
}
})
override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
2023-01-27 08:45:31 +00:00
override suspend fun invalidate() = kvCache.clear()
2021-03-24 07:01:15 +00:00
}
2022-06-29 20:44:44 +00:00
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
kvCache: KVCache<Key, List<Value>>
) = ReadKeyValuesCacheRepo(this, kvCache)
open class KeyValuesCacheRepo<Key,Value>(
parentRepo: KeyValuesRepo<Key, Value>,
kvCache: KVCache<Key, List<Value>>,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
2023-01-27 08:45:31 +00:00
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CommonCacheRepo {
2022-09-07 14:01:13 +00:00
protected val onNewJob = parentRepo.onNewValue.onEach { (k, v) ->
kvCache.set(
k,
kvCache.get(k) ?.plus(v) ?: return@onEach
)
}.launchIn(scope)
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { (k, v) ->
kvCache.set(
k,
kvCache.get(k) ?.minus(v) ?: return@onEach
)
}.launchIn(scope)
protected val onDataClearedJob = parentRepo.onDataCleared.onEach {
kvCache.unset(it)
}.launchIn(scope)
2023-01-27 08:45:31 +00:00
override suspend fun invalidate() = kvCache.clear()
}
2022-06-29 20:44:44 +00:00
fun <Key, Value> KeyValuesRepo<Key, Value>.cached(
kvCache: KVCache<Key, List<Value>>,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) = KeyValuesCacheRepo(this, kvCache, scope)