mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-12-24 17:47:15 +00:00
add FullKeyValuesCacheRepoTests and small rewrite of MapWriteKeyValuesRepo.set(Map<Key, List<Value>>) function
This commit is contained in:
parent
892fa90c37
commit
120e7228c7
@ -154,6 +154,28 @@ open class FullKeyValueCacheRepo<Key,Value>(
|
||||
parentRepo.clear()
|
||||
kvCache.clear()
|
||||
}
|
||||
|
||||
override suspend fun set(toSet: Map<Key, Value>) {
|
||||
locker.withWriteLock {
|
||||
super.set(toSet)
|
||||
kvCache.set(
|
||||
toSet.filter {
|
||||
parentRepo.contains(it.key)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun unset(toUnset: List<Key>) {
|
||||
locker.withWriteLock {
|
||||
super.unset(toUnset)
|
||||
kvCache.unset(
|
||||
toUnset.filter {
|
||||
!parentRepo.contains(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <Key, Value> KeyValueRepo<Key, Value>.fullyCached(
|
||||
|
@ -65,6 +65,42 @@ open class FullReadKeyValuesCacheRepo<Key,Value>(
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getAll(k: Key, reversed: Boolean): List<Value> {
|
||||
return doOrTakeAndActualizeWithWriteLock(
|
||||
{
|
||||
get(k) ?.optionallyReverse(reversed).optionalOrAbsentIfNull
|
||||
},
|
||||
{ getAll(k, reversed) },
|
||||
{ kvCache.set(k, it.optionallyReverse(reversed)) }
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getAll(reverseLists: Boolean): Map<Key, List<Value>> {
|
||||
return doOrTakeAndActualizeWithWriteLock(
|
||||
{
|
||||
getAll().takeIf { it.isNotEmpty() } ?.let {
|
||||
if (reverseLists) {
|
||||
it.mapValues { it.value.reversed() }
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.optionalOrAbsentIfNull
|
||||
},
|
||||
{ getAll(reverseLists) },
|
||||
{
|
||||
kvCache.set(
|
||||
it.let {
|
||||
if (reverseLists) {
|
||||
it.mapValues { it.value.reversed() }
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> {
|
||||
return doOrTakeAndActualize(
|
||||
{
|
||||
@ -163,14 +199,15 @@ fun <Key, Value> WriteKeyValuesRepo<Key, Value>.caching(
|
||||
) = FullWriteKeyValuesCacheRepo(this, kvCache, scope, locker)
|
||||
|
||||
open class FullKeyValuesCacheRepo<Key,Value>(
|
||||
protected open val parentRepo: KeyValuesRepo<Key, Value>,
|
||||
override val parentRepo: KeyValuesRepo<Key, Value>,
|
||||
kvCache: KeyValueRepo<Key, List<Value>>,
|
||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||
skipStartInvalidate: Boolean = false,
|
||||
locker: SmartRWLocker = SmartRWLocker(),
|
||||
) : FullWriteKeyValuesCacheRepo<Key, Value>(parentRepo, kvCache, scope, locker),
|
||||
) : //FullWriteKeyValuesCacheRepo<Key, Value>(parentRepo, kvCache, scope, locker),
|
||||
KeyValuesRepo<Key, Value>,
|
||||
ReadKeyValuesRepo<Key, Value> by FullReadKeyValuesCacheRepo(parentRepo, kvCache, locker) {
|
||||
FullReadKeyValuesCacheRepo<Key, Value>(parentRepo, kvCache, locker),
|
||||
WriteKeyValuesRepo<Key, Value> by parentRepo {
|
||||
init {
|
||||
if (!skipStartInvalidate) {
|
||||
scope.launchSafelyWithoutExceptions { invalidate() }
|
||||
@ -190,11 +227,63 @@ open class FullKeyValuesCacheRepo<Key,Value>(
|
||||
}
|
||||
|
||||
override suspend fun set(toSet: Map<Key, List<Value>>) {
|
||||
super<KeyValuesRepo>.set(toSet)
|
||||
locker.withWriteLock {
|
||||
parentRepo.set(toSet)
|
||||
kvCache.set(
|
||||
toSet.filter {
|
||||
parentRepo.contains(it.key)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeWithValue(v: Value) {
|
||||
super<FullWriteKeyValuesCacheRepo>.removeWithValue(v)
|
||||
override suspend fun add(toAdd: Map<Key, List<Value>>) {
|
||||
locker.withWriteLock {
|
||||
parentRepo.add(toAdd)
|
||||
toAdd.forEach {
|
||||
val filtered = it.value.filter { v ->
|
||||
parentRepo.contains(it.key, v)
|
||||
}.ifEmpty {
|
||||
return@forEach
|
||||
}
|
||||
kvCache.set(
|
||||
it.key,
|
||||
(kvCache.get(it.key) ?: emptyList()) + filtered
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
|
||||
locker.withWriteLock {
|
||||
parentRepo.remove(toRemove)
|
||||
toRemove.forEach {
|
||||
val filtered = it.value.filter { v ->
|
||||
!parentRepo.contains(it.key, v)
|
||||
}.ifEmpty {
|
||||
return@forEach
|
||||
}.toSet()
|
||||
val resultList = (kvCache.get(it.key) ?: emptyList()) - filtered
|
||||
if (resultList.isEmpty()) {
|
||||
kvCache.unset(it.key)
|
||||
} else {
|
||||
kvCache.set(
|
||||
it.key,
|
||||
resultList
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun clear(k: Key) {
|
||||
locker.withWriteLock {
|
||||
parentRepo.clear(k)
|
||||
if (parentRepo.contains(k)) {
|
||||
return@withWriteLock
|
||||
}
|
||||
kvCache.unset(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
56
repos/cache/src/commonTest/kotlin/full/FullKeyValuesCacheRepoTests.kt
vendored
Normal file
56
repos/cache/src/commonTest/kotlin/full/FullKeyValuesCacheRepoTests.kt
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
package full
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import dev.inmo.micro_utils.repos.*
|
||||
import dev.inmo.micro_utils.repos.cache.full.FullKeyValuesCacheRepo
|
||||
import korlibs.time.days
|
||||
import korlibs.time.years
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.test.*
|
||||
|
||||
class FullKeyValuesCacheRepoTests {
|
||||
@Test
|
||||
fun creatingWorksProperly() = runTest(timeout = 1.days) {
|
||||
val testData = (0 until 1000).associate {
|
||||
(it.toString() + uuid4().toString()) to (0 until 1000).map {
|
||||
uuid4().toString()
|
||||
}.sorted()
|
||||
}
|
||||
val updatedTestData = testData.keys.associateWith {
|
||||
(0 until 1000).map {
|
||||
uuid4().toString()
|
||||
}.sorted()
|
||||
}
|
||||
val addedData = testData.keys.associateWith {
|
||||
uuid4().toString()
|
||||
}
|
||||
val kvCache = MapKeyValueRepo<String, List<String>>()
|
||||
val kvRepo = MapKeyValuesRepo<String, String>()
|
||||
|
||||
val cacheRepo = FullKeyValuesCacheRepo(
|
||||
kvRepo,
|
||||
kvCache
|
||||
)
|
||||
|
||||
testData.forEach {
|
||||
cacheRepo.set(it.key, it.value)
|
||||
assertContentEquals(it.value, cacheRepo.getAll(it.key))
|
||||
assertContentEquals(it.value, kvRepo.getAll(it.key))
|
||||
assertContentEquals(it.value, kvCache.get(it.key) ?.sorted())
|
||||
}
|
||||
|
||||
updatedTestData.forEach {
|
||||
cacheRepo.set(it.key, it.value)
|
||||
assertContentEquals(it.value, cacheRepo.getAll(it.key))
|
||||
assertContentEquals(it.value, kvRepo.getAll(it.key))
|
||||
assertContentEquals(it.value, kvCache.get(it.key) ?.sorted())
|
||||
}
|
||||
|
||||
addedData.forEach {
|
||||
cacheRepo.add(it.key, it.value)
|
||||
assertTrue(cacheRepo.contains(it.key, it.value))
|
||||
assertTrue(kvRepo.contains(it.key, it.value))
|
||||
assertTrue(kvCache.get(it.key) !!.contains(it.value))
|
||||
}
|
||||
}
|
||||
}
|
@ -108,6 +108,19 @@ class MapWriteKeyValuesRepo<Key, Value>(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun set(toSet: Map<Key, List<Value>>) {
|
||||
locker.withWriteLock {
|
||||
toSet.forEach {
|
||||
map[it.key] = it.value.toMutableList()
|
||||
}
|
||||
}
|
||||
toSet.forEach { (k, v) ->
|
||||
v.forEach {
|
||||
_onNewValue.emit(k to it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
|
||||
val removed = mutableListOf<Pair<Key, Value>>()
|
||||
val cleared = mutableListOf<Key>()
|
||||
|
Loading…
Reference in New Issue
Block a user