From 0f8b69aa60feb7ff2474571b5c72bde23e2333dc Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 20:34:50 +0600 Subject: [PATCH 01/25] start 0.16.8 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index bba345e0759..ecd020b6e6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,5 +14,5 @@ crypto_js_version=4.1.1 # Project data group=dev.inmo -version=0.16.7 -android_code_version=175 +version=0.16.8 +android_code_version=176 From 605f55acd24411db6cf622537578b104f7b354ab Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 20:34:27 +0600 Subject: [PATCH 02/25] fixes in Write* cache repos --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18b8bd0ba82..e1adb16ba77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.16.8 + +* `Repos`: + * `Cache`: + * Fixes in `Write*` variants of cached repos + ## 0.16.7 * `Common`: From 46178e723b9422c544516b39b9d202be89497999 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 20:54:32 +0600 Subject: [PATCH 03/25] fixes --- .../inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt | 2 -- .../micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt | 5 +++-- .../micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) 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 7878d897668..0b18d436001 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 @@ -3,11 +3,9 @@ package dev.inmo.micro_utils.repos.cache.full import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.PaginationResult -import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.cache.* import dev.inmo.micro_utils.repos.cache.cache.FullKVCache -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.Dispatchers 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 635e5754724..81927bb1b80 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 @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.pagination.getAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.* open class FullReadKeyValueCacheRepo( @@ -80,7 +81,7 @@ fun ReadKeyValueRepo.cached( ) = FullReadKeyValueCacheRepo(this, kvCache) open class FullWriteKeyValueCacheRepo( - protected open val parentRepo: WriteKeyValueRepo, + parentRepo: WriteKeyValueRepo, protected open val kvCache: FullKVCache, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) : WriteKeyValueRepo by parentRepo, FullCacheRepo { @@ -98,7 +99,7 @@ fun WriteKeyValueRepo.caching( ) = FullWriteKeyValueCacheRepo(this, kvCache, scope) open class FullKeyValueCacheRepo( - override val parentRepo: KeyValueRepo, + protected open val parentRepo: KeyValueRepo, kvCache: FullKVCache, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) : FullWriteKeyValueCacheRepo(parentRepo, kvCache, scope), 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 e91ef6dbcb1..fc4bf34db0b 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 @@ -112,7 +112,7 @@ fun ReadKeyValuesRepo.cached( ) = FullReadKeyValuesCacheRepo(this, kvCache) open class FullWriteKeyValuesCacheRepo( - protected open val parentRepo: WriteKeyValuesRepo, + parentRepo: WriteKeyValuesRepo, protected open val kvCache: FullKVCache>, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) : WriteKeyValuesRepo by parentRepo, FullCacheRepo { @@ -140,7 +140,7 @@ fun WriteKeyValuesRepo.caching( ) = FullWriteKeyValuesCacheRepo(this, kvCache, scope) open class FullKeyValuesCacheRepo( - override val parentRepo: KeyValuesRepo, + protected open val parentRepo: KeyValuesRepo, kvCache: FullKVCache>, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) ) : FullWriteKeyValuesCacheRepo(parentRepo, kvCache, scope), From e6d9c8250f8fc2e752f2d47b3bcda65ac82ce28d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 22:18:22 +0600 Subject: [PATCH 04/25] add all autorecaches repos --- .../repos/cache/fallback/ActionWrapper.kt | 19 +++ .../fallback/crud/AutoRecacheCRUDRepo.kt | 36 +++++ .../fallback/crud/AutoRecacheReadCRUDRepo.kt | 77 ++++++++++ .../fallback/crud/AutoRecacheWriteCRUDRepo.kt | 60 ++++++++ .../keyvalue/AutoRecacheKeyValueRepo.kt | 42 ++++++ .../keyvalue/AutoRecacheReadKeyValueRepo.kt | 87 +++++++++++ .../keyvalue/AutoRecacheWriteKeyValueRepo.kt | 49 +++++++ .../keyvalues/AutoRecacheKeyValueRepo.kt | 40 +++++ .../keyvalues/AutoRecacheReadKeyValuesRepo.kt | 138 ++++++++++++++++++ .../AutoRecacheWriteKeyValuesRepo.kt | 81 ++++++++++ 10 files changed, 629 insertions(+) create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheCRUDRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheKeyValueRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt new file mode 100644 index 00000000000..abc2a78718e --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt @@ -0,0 +1,19 @@ +package dev.inmo.micro_utils.repos.cache.fallback + +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import kotlinx.coroutines.withTimeout + +interface ActionWrapper { + suspend fun wrap(block: suspend () -> T): Result + + class Timeouted(private val timeoutMillis: Long) : ActionWrapper { + override suspend fun wrap(block: suspend () -> T): Result = runCatchingSafely { + withTimeout(timeoutMillis) { + block() + } + } + } + object Direct : ActionWrapper { + override suspend fun wrap(block: suspend () -> T): Result = runCatchingSafely { block() } + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheCRUDRepo.kt new file mode 100644 index 00000000000..cc28b5245d7 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheCRUDRepo.kt @@ -0,0 +1,36 @@ +package dev.inmo.micro_utils.repos.cache.fallback.crud + +import dev.inmo.micro_utils.repos.CRUDRepo +import dev.inmo.micro_utils.repos.WriteCRUDRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import kotlinx.coroutines.CoroutineScope +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheCRUDRepo( + originalRepo: CRUDRepo, + scope: CoroutineScope, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + actionWrapper: ActionWrapper = ActionWrapper.Direct, + idGetter: (RegisteredObject) -> Id +) : AutoRecacheReadCRUDRepo( + originalRepo, + scope, + kvCache, + recacheDelay, + actionWrapper, + idGetter +), + WriteCRUDRepo by AutoRecacheWriteCRUDRepo(originalRepo, scope, kvCache, idGetter), + CRUDRepo { + + constructor( + originalRepo: CRUDRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt new file mode 100644 index 00000000000..0ba56f67e29 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt @@ -0,0 +1,77 @@ +package dev.inmo.micro_utils.repos.cache.fallback.crud + +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.repos.ReadCRUDRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import dev.inmo.micro_utils.repos.cache.util.actualizeAll +import dev.inmo.micro_utils.repos.set +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheReadCRUDRepo( + protected val originalRepo: ReadCRUDRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache = FullKVCache(), + protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, + protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, + protected val idGetter: (RegisteredObject) -> Id +) : ReadCRUDRepo { + val autoUpdateJob = scope.launch { + while (isActive) { + runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + + delay(recacheDelay) + } + } + + constructor( + originalRepo: ReadCRUDRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + + override suspend fun contains(id: Id): Boolean = actionWrapper.wrap { + originalRepo.contains(id) + }.getOrElse { + kvCache.contains(id) + } + + override suspend fun count(): Long = actionWrapper.wrap { + originalRepo.count() + }.getOrElse { + kvCache.count() + } + + override suspend fun getByPagination( + pagination: Pagination + ): PaginationResult = actionWrapper.wrap { + originalRepo.getByPagination(pagination) + }.getOrNull() ?.also { + it.results.forEach { + kvCache.set(idGetter(it), it) + } + } ?: kvCache.values(pagination) + + override suspend fun getIdsByPagination( + pagination: Pagination + ): PaginationResult = actionWrapper.wrap { + originalRepo.getIdsByPagination(pagination) + }.getOrElse { kvCache.keys(pagination) } + + override suspend fun getById(id: Id): RegisteredObject? = actionWrapper.wrap { + originalRepo.getById(id) + }.getOrNull() ?.also { + kvCache.set(idGetter(it), it) + } ?: kvCache.get(id) +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt new file mode 100644 index 00000000000..19632663e21 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt @@ -0,0 +1,60 @@ +package dev.inmo.micro_utils.repos.cache.fallback.crud + +import dev.inmo.micro_utils.coroutines.plus +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.repos.UpdatedValuePair +import dev.inmo.micro_utils.repos.WriteCRUDRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.set +import dev.inmo.micro_utils.repos.unset +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge + +open class AutoRecacheWriteCRUDRepo( + protected val originalRepo: WriteCRUDRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache = FullKVCache(), + protected val idGetter: (RegisteredObject) -> Id +) : WriteCRUDRepo { + override val deletedObjectsIdsFlow: Flow + get() = (originalRepo.deletedObjectsIdsFlow + kvCache.onValueRemoved).distinctUntilChanged() + override val newObjectsFlow: Flow + get() = (originalRepo.newObjectsFlow + kvCache.onNewValue.map { it.second }).distinctUntilChanged() + override val updatedObjectsFlow: Flow + get() = originalRepo.updatedObjectsFlow + + private val onRemovingUpdatesListeningJob = originalRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(scope) { + kvCache.unset(it) + } + + private val onNewAndUpdatedObjectsListeningJob = merge( + originalRepo.newObjectsFlow, + originalRepo.updatedObjectsFlow, + ).subscribeSafelyWithoutExceptions(scope) { + kvCache.set(idGetter(it), it) + } + + override suspend fun update( + values: List> + ): List = originalRepo.update(values).onEach { + kvCache.set(idGetter(it), it) + } + + override suspend fun update( + id: Id, + value: InputObject + ): RegisteredObject? = originalRepo.update(id, value) ?.also { + kvCache.set(idGetter(it), it) + } + + override suspend fun deleteById(ids: List) = originalRepo.deleteById(ids).also { + kvCache.unset(ids) + } + + override suspend fun create(values: List): List = originalRepo.create(values).onEach { + kvCache.set(idGetter(it), it) + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheKeyValueRepo.kt new file mode 100644 index 00000000000..e1864829e3c --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheKeyValueRepo.kt @@ -0,0 +1,42 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalue + +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.micro_utils.repos.WriteKeyValueRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import kotlinx.coroutines.CoroutineScope +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheKeyValueRepo( + override val originalRepo: KeyValueRepo, + scope: CoroutineScope, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + actionWrapper: ActionWrapper = ActionWrapper.Direct, + idGetter: (RegisteredObject) -> Id +) : AutoRecacheReadKeyValueRepo ( + originalRepo, + scope, + kvCache, + recacheDelay, + actionWrapper, + idGetter +), + WriteKeyValueRepo by AutoRecacheWriteKeyValueRepo(originalRepo, scope, kvCache), + KeyValueRepo { + + constructor( + originalRepo: KeyValueRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + + override suspend fun unsetWithValues(toUnset: List) = originalRepo.unsetWithValues( + toUnset + ).also { + kvCache.unsetWithValues(toUnset) + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt new file mode 100644 index 00000000000..58d90ca310e --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -0,0 +1,87 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalue + +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import dev.inmo.micro_utils.repos.cache.util.actualizeAll +import dev.inmo.micro_utils.repos.set +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheReadKeyValueRepo( + protected open val originalRepo: ReadKeyValueRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache = FullKVCache(), + protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, + protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, + protected val idGetter: (RegisteredObject) -> Id +) : ReadKeyValueRepo { + val autoUpdateJob = scope.launch { + while (isActive) { + runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + + delay(recacheDelay) + } + } + + constructor( + originalRepo: ReadKeyValueRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + + override suspend fun contains(key: Id): Boolean = actionWrapper.wrap { + originalRepo.contains(key) + }.getOrElse { + kvCache.contains(key) + } + + override suspend fun count(): Long = actionWrapper.wrap { + originalRepo.count() + }.getOrElse { + kvCache.count() + } + + override suspend fun get(k: Id): RegisteredObject? = actionWrapper.wrap { + originalRepo.get(k) + }.getOrNull() ?.also { + kvCache.set(idGetter(it), it) + } ?: kvCache.get(k) + + override suspend fun values( + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.values(pagination, reversed) + }.getOrNull() ?.also { + it.results.forEach { + kvCache.set(idGetter(it), it) + } + } ?: kvCache.values(pagination, reversed) + + override suspend fun keys( + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.keys(pagination, reversed) + }.getOrElse { kvCache.keys(pagination, reversed) } + + override suspend fun keys( + v: RegisteredObject, + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.keys(v, pagination, reversed) + }.getOrElse { kvCache.keys(v, pagination, reversed) } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt new file mode 100644 index 00000000000..ca91a0a19f2 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt @@ -0,0 +1,49 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalue + +import dev.inmo.micro_utils.coroutines.plus +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.repos.WriteKeyValueRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.set +import dev.inmo.micro_utils.repos.unset +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged + +open class AutoRecacheWriteKeyValueRepo( + protected val originalRepo: WriteKeyValueRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache = FullKVCache() +) : WriteKeyValueRepo { + override val onValueRemoved: Flow + get() = (originalRepo.onValueRemoved + kvCache.onValueRemoved).distinctUntilChanged() + + override val onNewValue: Flow> + get() = (originalRepo.onNewValue + kvCache.onNewValue).distinctUntilChanged() + + private val onRemovingUpdatesListeningJob = originalRepo.onValueRemoved.subscribeSafelyWithoutExceptions(scope) { + kvCache.unset(it) + } + + private val onNewAndUpdatedObjectsListeningJob = originalRepo.onNewValue.subscribeSafelyWithoutExceptions(scope) { + kvCache.set(it.first, it.second) + } + + override suspend fun unsetWithValues(toUnset: List) = originalRepo.unsetWithValues( + toUnset + ).also { + kvCache.unsetWithValues(toUnset) + } + + override suspend fun unset(toUnset: List) = originalRepo.unset( + toUnset + ).also { + kvCache.unset(toUnset) + } + + override suspend fun set(toSet: Map) = originalRepo.set( + toSet + ).also { + kvCache.set(toSet) + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt new file mode 100644 index 00000000000..8527e89ecf5 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt @@ -0,0 +1,40 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalues + +import dev.inmo.micro_utils.repos.KeyValuesRepo +import dev.inmo.micro_utils.repos.WriteKeyValuesRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import kotlinx.coroutines.CoroutineScope +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheKeyValuesRepo( + override val originalRepo: KeyValuesRepo, + scope: CoroutineScope, + kvCache: FullKVCache> = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + actionWrapper: ActionWrapper = ActionWrapper.Direct, + idGetter: (RegisteredObject) -> Id +) : AutoRecacheReadKeyValuesRepo ( + originalRepo, + scope, + kvCache, + recacheDelay, + actionWrapper, + idGetter +), + WriteKeyValuesRepo by AutoRecacheWriteKeyValuesRepo(originalRepo, scope, kvCache), + KeyValuesRepo { + + constructor( + originalRepo: KeyValuesRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache> = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + + override suspend fun clearWithValue(v: RegisteredObject) { + super.clearWithValue(v) + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt new file mode 100644 index 00000000000..918f7083491 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt @@ -0,0 +1,138 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalues + +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.pagination.changeResultsUnchecked +import dev.inmo.micro_utils.pagination.createPaginationResult +import dev.inmo.micro_utils.pagination.emptyPaginationResult +import dev.inmo.micro_utils.pagination.firstIndex +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.pagination.utils.optionallyReverse +import dev.inmo.micro_utils.pagination.utils.paginate +import dev.inmo.micro_utils.repos.ReadKeyValuesRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper +import dev.inmo.micro_utils.repos.cache.util.actualizeAll +import dev.inmo.micro_utils.repos.set +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.seconds + +open class AutoRecacheReadKeyValuesRepo( + protected open val originalRepo: ReadKeyValuesRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache> = FullKVCache(), + protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, + protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, + protected val idGetter: (RegisteredObject) -> Id +) : ReadKeyValuesRepo { + val autoUpdateJob = scope.launch { + while (isActive) { + runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + + delay(recacheDelay) + } + } + + constructor( + originalRepo: ReadKeyValuesRepo, + scope: CoroutineScope, + originalCallTimeoutMillis: Long, + kvCache: FullKVCache> = FullKVCache(), + recacheDelay: Long = 60.seconds.inWholeMilliseconds, + idGetter: (RegisteredObject) -> Id + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + + override suspend fun contains(k: Id): Boolean = actionWrapper.wrap { + originalRepo.contains(k) + }.getOrElse { + kvCache.contains(k) + } + + override suspend fun count(): Long = actionWrapper.wrap { + originalRepo.count() + }.getOrElse { + kvCache.count() + } + + override suspend fun keys( + v: RegisteredObject, + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.keys(v, pagination, reversed) + }.getOrElse { + val results = mutableListOf() + + val toSkip = pagination.firstIndex + var count = 0 + + doForAllWithNextPaging { + kvCache.keys(pagination, reversed).also { + it.results.forEach { + if (kvCache.get(it) ?.contains(v) == true) { + count++ + if (count < toSkip || results.size >= pagination.size) { + return@forEach + } else { + results.add(it) + } + } + } + } + } + + return@getOrElse results.createPaginationResult( + pagination, + count.toLong() + ) + } + + override suspend fun keys( + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.keys(pagination, reversed) + }.getOrElse { kvCache.keys(pagination, reversed) } + + override suspend fun get( + k: Id, + pagination: Pagination, + reversed: Boolean + ): PaginationResult = actionWrapper.wrap { + originalRepo.get(k, pagination, reversed) + }.getOrNull() ?.also { + it.results.forEach { + kvCache.set(k, ((kvCache.get(k) ?: return@also) + it).distinct()) + } + } ?: kvCache.get(k) ?.run { + paginate(pagination.optionallyReverse(size, reversed)).let { + if (reversed) { + it.changeResultsUnchecked( + it.results.reversed() + ) + } else { + it + } + } + } ?: emptyPaginationResult() + + override suspend fun count(k: Id): Long = actionWrapper.wrap { + originalRepo.count(k) + }.getOrElse { + kvCache.get(k) ?.size ?.toLong() ?: 0L + } + + override suspend fun contains(k: Id, v: RegisteredObject): Boolean { + return (actionWrapper.wrap { + originalRepo.contains(k, v) + }.getOrNull() ?.also { + kvCache.set(k, ((kvCache.get(k) ?: return@also) + v).distinct()) + }) ?: (kvCache.get(k) ?.contains(v) == true) + } +} diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt new file mode 100644 index 00000000000..4c57b3b7f5d --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt @@ -0,0 +1,81 @@ +package dev.inmo.micro_utils.repos.cache.fallback.keyvalues + +import dev.inmo.micro_utils.coroutines.plus +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.repos.WriteKeyValuesRepo +import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.set +import dev.inmo.micro_utils.repos.unset +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged + +open class AutoRecacheWriteKeyValuesRepo( + protected val originalRepo: WriteKeyValuesRepo, + protected val scope: CoroutineScope, + protected val kvCache: FullKVCache> = FullKVCache() +) : WriteKeyValuesRepo { + override val onValueRemoved: Flow> + get() = originalRepo.onValueRemoved + + override val onNewValue: Flow> + get() = originalRepo.onNewValue + override val onDataCleared: Flow + get() = (originalRepo.onDataCleared + kvCache.onValueRemoved).distinctUntilChanged() + + private val onDataClearedListeningJob = originalRepo.onDataCleared.subscribeSafelyWithoutExceptions(scope) { + kvCache.unset(it) + } + + private val onRemovingUpdatesListeningJob = originalRepo.onValueRemoved.subscribeSafelyWithoutExceptions(scope) { + kvCache.set( + it.first, + (kvCache.get( + it.first + ) ?: return@subscribeSafelyWithoutExceptions) - it.second + ) + } + + private val onNewAndUpdatedObjectsListeningJob = originalRepo.onNewValue.subscribeSafelyWithoutExceptions(scope) { + kvCache.set( + it.first, + (kvCache.get( + it.first + ) ?: return@subscribeSafelyWithoutExceptions) + it.second + ) + } + + override suspend fun clearWithValue(v: RegisteredObject) { + originalRepo.clearWithValue(v) + doForAllWithNextPaging(FirstPagePagination(kvCache.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE)) { + kvCache.keys(it).also { + it.results.forEach { id -> + kvCache.get(id) ?.takeIf { it.contains(v) } ?.let { + kvCache.unset(id) + } + } + } + } + } + + override suspend fun clear(k: Id) { + originalRepo.clear(k) + kvCache.unset(k) + } + + override suspend fun remove(toRemove: Map>) { + originalRepo.remove(toRemove) + toRemove.forEach { (k, v) -> + kvCache.set(k, (kvCache.get(k) ?: return@forEach) - v) + } + } + + override suspend fun add(toAdd: Map>) { + originalRepo.add(toAdd) + toAdd.forEach { (k, v) -> + kvCache.set(k, (kvCache.get(k) ?: return@forEach) + v) + } + } +} From 6142022283fe626a2b88f2ba8f88f0ad907c4785 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 22:46:32 +0600 Subject: [PATCH 05/25] improve actualizeAll to lazily clear repo --- .../repos/cache/util/ActualizeAll.kt | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt index a657d6b8b45..7d90235adac 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt @@ -12,17 +12,25 @@ suspend inline fun KVCache.actualizeAll( getAll: () -> Map ) { clear() - set(getAll()) + set( + getAll().also { + clear() + } + ) } suspend inline fun KVCache.actualizeAll( repo: ReadKeyValueRepo ) { - clear() + var cleared = false val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE val initPagination = FirstPagePagination(count) doForAllWithNextPaging(initPagination) { keys(it).also { + if (!cleared) { + clear() + cleared = true + } set( it.results.mapNotNull { k -> repo.get(k) ?.let { k to it } } ) @@ -33,11 +41,15 @@ suspend inline fun KVCache.actualizeAll( suspend inline fun KVCache>.actualizeAll( repo: ReadKeyValuesRepo ) { - clear() + var cleared = false val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE val initPagination = FirstPagePagination(count) doForAllWithNextPaging(initPagination) { keys(it).also { + if (!cleared) { + clear() + cleared = true + } set( it.results.associateWith { k -> repo.getAll(k) } ) @@ -48,11 +60,15 @@ suspend inline fun KVCache>.actualizeAll( suspend inline fun KVCache.actualizeAll( repo: ReadCRUDRepo ) { - clear() + var cleared = false val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE val initPagination = FirstPagePagination(count) doForAllWithNextPaging(initPagination) { keys(it).also { + if (!cleared) { + clear() + cleared = true + } set( it.results.mapNotNull { k -> repo.getById(k) ?.let { k to it } } ) From 2162e83bce53738ea8997ed0866a9b85f16df731 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 29 Jan 2023 22:51:39 +0600 Subject: [PATCH 06/25] fixes in actualizeAll --- .../repos/cache/util/ActualizeAll.kt | 50 ++++--------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt index 7d90235adac..8eb15f14a96 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt @@ -2,16 +2,17 @@ package dev.inmo.micro_utils.repos.cache.util import dev.inmo.micro_utils.pagination.FirstPagePagination import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.pagination.utils.getAllByWithNextPaging import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.ReadKeyValueRepo import dev.inmo.micro_utils.repos.ReadKeyValuesRepo import dev.inmo.micro_utils.repos.cache.cache.KVCache +import dev.inmo.micro_utils.repos.pagination.getAll import dev.inmo.micro_utils.repos.set suspend inline fun KVCache.actualizeAll( getAll: () -> Map ) { - clear() set( getAll().also { clear() @@ -22,56 +23,25 @@ suspend inline fun KVCache.actualizeAll( suspend inline fun KVCache.actualizeAll( repo: ReadKeyValueRepo ) { - var cleared = false - val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE - val initPagination = FirstPagePagination(count) - doForAllWithNextPaging(initPagination) { - keys(it).also { - if (!cleared) { - clear() - cleared = true - } - set( - it.results.mapNotNull { k -> repo.get(k) ?.let { k to it } } - ) - } + actualizeAll { + repo.getAll { keys(it) }.toMap() } } suspend inline fun KVCache>.actualizeAll( repo: ReadKeyValuesRepo ) { - var cleared = false - val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE - val initPagination = FirstPagePagination(count) - doForAllWithNextPaging(initPagination) { - keys(it).also { - if (!cleared) { - clear() - cleared = true - } - set( - it.results.associateWith { k -> repo.getAll(k) } - ) - } + actualizeAll { + repo.getAll { keys(it) }.toMap() } } suspend inline fun KVCache.actualizeAll( repo: ReadCRUDRepo ) { - var cleared = false - val count = repo.count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE - val initPagination = FirstPagePagination(count) - doForAllWithNextPaging(initPagination) { - keys(it).also { - if (!cleared) { - clear() - cleared = true - } - set( - it.results.mapNotNull { k -> repo.getById(k) ?.let { k to it } } - ) - } + actualizeAll { + repo.getAllByWithNextPaging { + getIdsByPagination(it) + }.mapNotNull { it to (repo.getById(it) ?: return@mapNotNull null) }.toMap() } } From 428eabb1bde624c51c8af6d791df595420dcfe1b Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:54:32 +0600 Subject: [PATCH 07/25] Create FallbackCacheRepo.kt --- .../dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt new file mode 100644 index 00000000000..a1130e8f645 --- /dev/null +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt @@ -0,0 +1,7 @@ +package dev.inmo.micro_utils.repos.cache + +/** + * Any inheritor of this should work with next logic: try to take data from their original repo, if successful - save data to internal + * [dev.inmo.micro_utils.repos.cache.cache.FullKVCache] or try to take data from that internal cache + */ +interface FallbackCacheRepo : CacheRepo From b64f2e6d32b7967a7a2f2fad2b9768c57421241c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:56:57 +0600 Subject: [PATCH 08/25] Update AutoRecacheWriteKeyValuesRepo.kt --- .../cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt index 4c57b3b7f5d..9516a16bf8f 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt @@ -6,6 +6,7 @@ import dev.inmo.micro_utils.pagination.FirstPagePagination import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging import dev.inmo.micro_utils.repos.WriteKeyValuesRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import dev.inmo.micro_utils.repos.unset import kotlinx.coroutines.CoroutineScope @@ -16,7 +17,7 @@ open class AutoRecacheWriteKeyValuesRepo( protected val originalRepo: WriteKeyValuesRepo, protected val scope: CoroutineScope, protected val kvCache: FullKVCache> = FullKVCache() -) : WriteKeyValuesRepo { +) : WriteKeyValuesRepo, FallbackCacheRepo { override val onValueRemoved: Flow> get() = originalRepo.onValueRemoved From 681c13144a0f65e632e7417c5534a9abc5ab3872 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:57:40 +0600 Subject: [PATCH 09/25] Update AutoRecacheReadKeyValuesRepo.kt --- .../cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt index 918f7083491..c160f61c320 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt @@ -14,6 +14,7 @@ import dev.inmo.micro_utils.repos.ReadKeyValuesRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache 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.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -28,7 +29,7 @@ open class AutoRecacheReadKeyValuesRepo( protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, protected val idGetter: (RegisteredObject) -> Id -) : ReadKeyValuesRepo { +) : ReadKeyValuesRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { runCatchingSafely { From 3d90df689781b053a12dbafaea9358dd5f368358 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:58:11 +0600 Subject: [PATCH 10/25] Update AutoRecacheWriteKeyValueRepo.kt --- .../cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt index ca91a0a19f2..fef2e946046 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt @@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.plus import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.repos.WriteKeyValueRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import dev.inmo.micro_utils.repos.unset import kotlinx.coroutines.CoroutineScope @@ -14,7 +15,7 @@ open class AutoRecacheWriteKeyValueRepo( protected val originalRepo: WriteKeyValueRepo, protected val scope: CoroutineScope, protected val kvCache: FullKVCache = FullKVCache() -) : WriteKeyValueRepo { +) : WriteKeyValueRepo, FallbackCacheRepo { override val onValueRemoved: Flow get() = (originalRepo.onValueRemoved + kvCache.onValueRemoved).distinctUntilChanged() From 8a890ed6ed46676920ed350362e23fd8044776b4 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:58:43 +0600 Subject: [PATCH 11/25] Update AutoRecacheReadKeyValueRepo.kt --- .../cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt index 58d90ca310e..3eb121589de 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache 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.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -21,7 +22,7 @@ open class AutoRecacheReadKeyValueRepo( protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, protected val idGetter: (RegisteredObject) -> Id -) : ReadKeyValueRepo { +) : ReadKeyValueRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { runCatchingSafely { From 4a7567f288cb5a5f259f012e3f9aed0d50a038a5 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:59:19 +0600 Subject: [PATCH 12/25] Update AutoRecacheWriteCRUDRepo.kt --- .../repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt index 19632663e21..9a044ab254d 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt @@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.repos.UpdatedValuePair import dev.inmo.micro_utils.repos.WriteCRUDRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache +import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import dev.inmo.micro_utils.repos.unset import kotlinx.coroutines.CoroutineScope @@ -18,7 +19,7 @@ open class AutoRecacheWriteCRUDRepo( protected val scope: CoroutineScope, protected val kvCache: FullKVCache = FullKVCache(), protected val idGetter: (RegisteredObject) -> Id -) : WriteCRUDRepo { +) : WriteCRUDRepo, FallbackCacheRepo { override val deletedObjectsIdsFlow: Flow get() = (originalRepo.deletedObjectsIdsFlow + kvCache.onValueRemoved).distinctUntilChanged() override val newObjectsFlow: Flow From 79f20415657a8c464d098df7e12ef6978e199b13 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 30 Jan 2023 23:59:48 +0600 Subject: [PATCH 13/25] Update AutoRecacheReadCRUDRepo.kt --- .../repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt index 0ba56f67e29..14c3ed29800 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.cache.cache.FullKVCache 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.FallbackCacheRepo import dev.inmo.micro_utils.repos.set import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -21,7 +22,7 @@ open class AutoRecacheReadCRUDRepo( protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, protected val idGetter: (RegisteredObject) -> Id -) : ReadCRUDRepo { +) : ReadCRUDRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { runCatchingSafely { From 2645ea29d6a3c494298b28874d42db8ee5cce718 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 31 Jan 2023 00:11:45 +0600 Subject: [PATCH 14/25] Update ActionWrapper.kt --- .../repos/cache/fallback/ActionWrapper.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt index abc2a78718e..11a96e71978 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/ActionWrapper.kt @@ -3,9 +3,23 @@ package dev.inmo.micro_utils.repos.cache.fallback import dev.inmo.micro_utils.coroutines.runCatchingSafely import kotlinx.coroutines.withTimeout +/** + * Realizations should [wrap] the work with some conditions like retries on exceptions, calling timeout, etc. + * + * @see Timeouted + * @see Direct + */ interface ActionWrapper { + /** + * Should execute [block] to take the result [T], but may return failure in case when something went wrong. + * This method should never throw any [Exception] + */ suspend fun wrap(block: suspend () -> T): Result + /** + * This type of [ActionWrapper]s will use [withTimeout]([timeoutMillis]) and if original call + * will not return anything in that timeout just return [Result] with failure + */ class Timeouted(private val timeoutMillis: Long) : ActionWrapper { override suspend fun wrap(block: suspend () -> T): Result = runCatchingSafely { withTimeout(timeoutMillis) { @@ -13,7 +27,11 @@ interface ActionWrapper { } } } + /** + * It is passthrough variant of [ActionWrapper] which will just call incoming block with wrapping into [runCatchingSafely] + */ object Direct : ActionWrapper { + override suspend fun wrap(block: suspend () -> T): Result = runCatchingSafely { block() } } } From 3f6f6ebc2bcfb5242511e1f1228207ad56347939 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 31 Jan 2023 10:09:55 +0600 Subject: [PATCH 15/25] realize invalidate method in fallback cache repos --- .../fallback/crud/AutoRecacheReadCRUDRepo.kt | 16 ++++++++++++---- .../fallback/crud/AutoRecacheWriteCRUDRepo.kt | 4 ++++ .../keyvalue/AutoRecacheReadKeyValueRepo.kt | 14 +++++++++++--- .../keyvalue/AutoRecacheWriteKeyValueRepo.kt | 4 ++++ .../keyvalues/AutoRecacheReadKeyValuesRepo.kt | 14 +++++++++++--- .../keyvalues/AutoRecacheWriteKeyValuesRepo.kt | 4 ++++ 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt index 14c3ed29800..de4a0a14acd 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt @@ -16,7 +16,7 @@ import kotlinx.coroutines.launch import kotlin.time.Duration.Companion.seconds open class AutoRecacheReadCRUDRepo( - protected val originalRepo: ReadCRUDRepo, + protected open val originalRepo: ReadCRUDRepo, protected val scope: CoroutineScope, protected val kvCache: FullKVCache = FullKVCache(), protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, @@ -25,9 +25,7 @@ open class AutoRecacheReadCRUDRepo( ) : ReadCRUDRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { - runCatchingSafely { - kvCache.actualizeAll(originalRepo) - } + actualizeAll() delay(recacheDelay) } @@ -42,6 +40,12 @@ open class AutoRecacheReadCRUDRepo( idGetter: (RegisteredObject) -> Id ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + protected suspend fun actualizeAll(): Result { + return runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + } + override suspend fun contains(id: Id): Boolean = actionWrapper.wrap { originalRepo.contains(id) }.getOrElse { @@ -75,4 +79,8 @@ open class AutoRecacheReadCRUDRepo( }.getOrNull() ?.also { kvCache.set(idGetter(it), it) } ?: kvCache.get(id) + + override suspend fun invalidate() { + actualizeAll() + } } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt index 9a044ab254d..ca15411096e 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheWriteCRUDRepo.kt @@ -58,4 +58,8 @@ open class AutoRecacheWriteCRUDRepo( override suspend fun create(values: List): List = originalRepo.create(values).onEach { kvCache.set(idGetter(it), it) } + + override suspend fun invalidate() { + kvCache.clear() + } } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt index 3eb121589de..0bc040bef7b 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -25,9 +25,7 @@ open class AutoRecacheReadKeyValueRepo( ) : ReadKeyValueRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { - runCatchingSafely { - kvCache.actualizeAll(originalRepo) - } + actualizeAll() delay(recacheDelay) } @@ -42,6 +40,12 @@ open class AutoRecacheReadKeyValueRepo( idGetter: (RegisteredObject) -> Id ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + protected suspend fun actualizeAll(): Result { + return runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + } + override suspend fun contains(key: Id): Boolean = actionWrapper.wrap { originalRepo.contains(key) }.getOrElse { @@ -85,4 +89,8 @@ open class AutoRecacheReadKeyValueRepo( ): PaginationResult = actionWrapper.wrap { originalRepo.keys(v, pagination, reversed) }.getOrElse { kvCache.keys(v, pagination, reversed) } + + override suspend fun invalidate() { + actualizeAll() + } } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt index fef2e946046..8a725629b36 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheWriteKeyValueRepo.kt @@ -47,4 +47,8 @@ open class AutoRecacheWriteKeyValueRepo( ).also { kvCache.set(toSet) } + + override suspend fun invalidate() { + kvCache.clear() + } } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt index c160f61c320..252e20872a7 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt @@ -32,9 +32,7 @@ open class AutoRecacheReadKeyValuesRepo( ) : ReadKeyValuesRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { - runCatchingSafely { - kvCache.actualizeAll(originalRepo) - } + actualizeAll() delay(recacheDelay) } @@ -49,6 +47,12 @@ open class AutoRecacheReadKeyValuesRepo( idGetter: (RegisteredObject) -> Id ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + protected suspend fun actualizeAll(): Result { + return runCatchingSafely { + kvCache.actualizeAll(originalRepo) + } + } + override suspend fun contains(k: Id): Boolean = actionWrapper.wrap { originalRepo.contains(k) }.getOrElse { @@ -136,4 +140,8 @@ open class AutoRecacheReadKeyValuesRepo( kvCache.set(k, ((kvCache.get(k) ?: return@also) + v).distinct()) }) ?: (kvCache.get(k) ?.contains(v) == true) } + + override suspend fun invalidate() { + actualizeAll() + } } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt index 9516a16bf8f..73cf0551472 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheWriteKeyValuesRepo.kt @@ -79,4 +79,8 @@ open class AutoRecacheWriteKeyValuesRepo( kvCache.set(k, (kvCache.get(k) ?: return@forEach) + v) } } + + override suspend fun invalidate() { + kvCache.clear() + } } From 47b0f6d2d8b54e2249ebe8c5bbe04d71a4fed22c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 1 Feb 2023 13:03:51 +0600 Subject: [PATCH 16/25] fixes --- .../dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt b/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt index 572785ca371..8031c347565 100644 --- a/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt +++ b/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt @@ -17,8 +17,11 @@ import io.ktor.http.HttpStatusCode import io.ktor.http.Parameters import io.ktor.http.content.PartData import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.SerializationStrategy import kotlinx.serialization.StringFormat import kotlinx.serialization.encodeToString +import kotlinx.serialization.serializer import java.io.File /** @@ -29,6 +32,7 @@ import java.io.File * in case you wish to pass other source of multipart binary data than regular file * @suppress */ +@OptIn(InternalSerializationApi::class) actual suspend fun HttpClient.uniUpload( url: String, data: Map, @@ -60,7 +64,7 @@ actual suspend fun HttpClient.uniUpload( ) else -> append( k, - stringFormat.encodeToString(v) + stringFormat.encodeToString(v::class.serializer() as SerializationStrategy, v) ) } } From 580d757be2d289d95f3916688c2bb44cfed0e038 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 1 Feb 2023 22:28:17 +0600 Subject: [PATCH 17/25] fixes in download file and upgrade ktor version --- gradle/libs.versions.toml | 2 +- .../dev/inmo/micro_utils/ktor/server/DownloadFileItem.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1f43dec4c89..51869c69f1c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ jb-dokka = "1.7.20" klock = "3.4.0" uuid = "0.6.0" -ktor = "2.2.2" +ktor = "2.2.3" gh-release = "2.4.1" diff --git a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/DownloadFileItem.kt b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/DownloadFileItem.kt index 2056a6e704b..998fef99797 100644 --- a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/DownloadFileItem.kt +++ b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/DownloadFileItem.kt @@ -10,8 +10,8 @@ import java.io.File fun PartData.FileItem.download(target: File) { provider().use { input -> - target.outputStream().use { - input.copyTo(it.asOutput()) + target.outputStream().asOutput().use { + input.copyTo(it) } } } From 442db122cfb7ce7cdbda7e773cff134c5a4c08af Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 1 Feb 2023 23:02:06 +0600 Subject: [PATCH 18/25] remove redundant id getter in keyvalues autocached repo --- .../fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt | 2 +- .../fallback/keyvalues/AutoRecacheKeyValueRepo.kt | 11 ++++------- .../keyvalues/AutoRecacheReadKeyValuesRepo.kt | 8 +++----- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt index 0bc040bef7b..1a46426d5e1 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -61,7 +61,7 @@ open class AutoRecacheReadKeyValueRepo( override suspend fun get(k: Id): RegisteredObject? = actionWrapper.wrap { originalRepo.get(k) }.getOrNull() ?.also { - kvCache.set(idGetter(it), it) + kvCache.set(k, it) } ?: kvCache.get(k) override suspend fun values( diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt index 8527e89ecf5..c51f852932c 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheKeyValueRepo.kt @@ -12,15 +12,13 @@ open class AutoRecacheKeyValuesRepo( scope: CoroutineScope, kvCache: FullKVCache> = FullKVCache(), recacheDelay: Long = 60.seconds.inWholeMilliseconds, - actionWrapper: ActionWrapper = ActionWrapper.Direct, - idGetter: (RegisteredObject) -> Id + actionWrapper: ActionWrapper = ActionWrapper.Direct ) : AutoRecacheReadKeyValuesRepo ( originalRepo, scope, kvCache, recacheDelay, - actionWrapper, - idGetter + actionWrapper ), WriteKeyValuesRepo by AutoRecacheWriteKeyValuesRepo(originalRepo, scope, kvCache), KeyValuesRepo { @@ -30,9 +28,8 @@ open class AutoRecacheKeyValuesRepo( scope: CoroutineScope, originalCallTimeoutMillis: Long, kvCache: FullKVCache> = FullKVCache(), - recacheDelay: Long = 60.seconds.inWholeMilliseconds, - idGetter: (RegisteredObject) -> Id - ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + recacheDelay: Long = 60.seconds.inWholeMilliseconds + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis)) override suspend fun clearWithValue(v: RegisteredObject) { super.clearWithValue(v) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt index 252e20872a7..9eec30e41c5 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt @@ -27,8 +27,7 @@ open class AutoRecacheReadKeyValuesRepo( protected val scope: CoroutineScope, protected val kvCache: FullKVCache> = FullKVCache(), protected val recacheDelay: Long = 60.seconds.inWholeMilliseconds, - protected val actionWrapper: ActionWrapper = ActionWrapper.Direct, - protected val idGetter: (RegisteredObject) -> Id + protected val actionWrapper: ActionWrapper = ActionWrapper.Direct ) : ReadKeyValuesRepo, FallbackCacheRepo { val autoUpdateJob = scope.launch { while (isActive) { @@ -43,9 +42,8 @@ open class AutoRecacheReadKeyValuesRepo( scope: CoroutineScope, originalCallTimeoutMillis: Long, kvCache: FullKVCache> = FullKVCache(), - recacheDelay: Long = 60.seconds.inWholeMilliseconds, - idGetter: (RegisteredObject) -> Id - ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) + recacheDelay: Long = 60.seconds.inWholeMilliseconds + ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis)) protected suspend fun actualizeAll(): Result { return runCatchingSafely { From 4f68459582c19d1a6c676697458328efdbd5c9c9 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 2 Feb 2023 10:15:37 +0600 Subject: [PATCH 19/25] start add kv to kvs transformations --- .../kv/ReadKeyValueFromKeyValuesRepo.kt | 69 +++++++++++++++++ .../kvs/ReadKeyValuesFromKeyValueRepo.kt | 74 +++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt new file mode 100644 index 00000000000..1f6582da2b4 --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt @@ -0,0 +1,69 @@ +package dev.inmo.micro_utils.repos.transforms.kv + +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.pagination.changeResults +import dev.inmo.micro_utils.pagination.changeResultsUnchecked +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.pagination.utils.optionallyReverse +import dev.inmo.micro_utils.pagination.utils.paginate +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import dev.inmo.micro_utils.repos.ReadKeyValuesRepo +import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo + +open class ReadKeyValueFromKeyValuesRepo( + private val original: ReadKeyValuesRepo +) : ReadKeyValueRepo> { + override suspend fun get(k: Key): List? = original.getAll(k) + + override suspend fun values( + pagination: Pagination, + reversed: Boolean + ): PaginationResult> { + val keys = keys(pagination, reversed) + return keys.changeResults( + keys.results.mapNotNull { + get(it) + } + ) + } + + override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult { + return original.keys(pagination, reversed) + } + + override suspend fun count(): Long { + return original.count() + } + + override suspend fun contains(key: Key): Boolean { + return original.contains(key) + } + + override suspend fun keys(v: List, pagination: Pagination, reversed: Boolean): PaginationResult { + val keys = mutableSetOf() + + doForAllWithNextPaging(FirstPagePagination(count().toInt())) { + original.keys(it).also { + it.results.forEach { + val values = get(it) ?: return@forEach + if (values.containsAll(v) && v.containsAll(values)) { + keys.add(it) + } + } + } + } + + val paginated = keys.paginate( + pagination.optionallyReverse(keys.count(), reversed) + ) + return if (reversed) { + paginated.changeResultsUnchecked(paginated.results.reversed()) + } else { + paginated + } + } +} + +fun ReadKeyValuesRepo.asReadKeyValueRepo() = ReadKeyValueFromKeyValuesRepo(this) diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt new file mode 100644 index 00000000000..cb9d752f9c2 --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt @@ -0,0 +1,74 @@ +package dev.inmo.micro_utils.repos.transforms.kvs + +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.pagination.changeResultsUnchecked +import dev.inmo.micro_utils.pagination.emptyPaginationResult +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.pagination.utils.optionallyReverse +import dev.inmo.micro_utils.pagination.utils.paginate +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import dev.inmo.micro_utils.repos.ReadKeyValuesRepo + +open class ReadKeyValuesFromKeyValueRepo>( + private val original: ReadKeyValueRepo +) : ReadKeyValuesRepo { + override suspend fun get( + k: Key, + pagination: Pagination, + reversed: Boolean + ): PaginationResult { + val iterable = original.get(k) ?: return emptyPaginationResult(pagination) + val paginated = iterable.paginate( + pagination.optionallyReverse(iterable.count(), reversed) + ) + return if (reversed) { + paginated.changeResultsUnchecked(paginated.results.reversed()) + } else { + paginated + } + } + + override suspend fun keys( + pagination: Pagination, + reversed: Boolean + ): PaginationResult = original.keys(pagination, reversed) + + override suspend fun count(): Long = original.count() + + override suspend fun count(k: Key): Long = original.get(k) ?.count() ?.toLong() ?: 0L + + override suspend fun contains(k: Key, v: Value): Boolean = original.get(k) ?.contains(v) == true + + override suspend fun contains(k: Key): Boolean = original.contains(k) + + override suspend fun keys( + v: Value, + pagination: Pagination, + reversed: Boolean + ): PaginationResult { + val keys = mutableSetOf() + + doForAllWithNextPaging(FirstPagePagination(count().toInt())) { + original.keys(it).also { + it.results.forEach { + if (contains(it, v)) { + keys.add(it) + } + } + } + } + + val paginated = keys.paginate( + pagination.optionallyReverse(keys.count(), reversed) + ) + return if (reversed) { + paginated.changeResultsUnchecked(paginated.results.reversed()) + } else { + paginated + } + } +} + +fun > ReadKeyValueRepo.asReadKeyValuesRepo() = ReadKeyValuesFromKeyValueRepo(this) From a5f718e25767e4de6e1d5028406cbded5d144b29 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 2 Feb 2023 12:29:00 +0600 Subject: [PATCH 20/25] add meppers for kv<->kvs repos --- .../repos/transforms/kv/Factories.kt | 12 +++ .../kv/KeyValueFromKeyValuesRepo.kt | 41 ++++++++++ .../kv/ReadKeyValueFromKeyValuesRepo.kt | 2 - .../repos/transforms/kvs/Factories.kt | 21 +++++ .../kvs/KeyValuesFromKeyValueRepo.kt | 77 +++++++++++++++++++ .../kvs/ReadKeyValuesFromKeyValueRepo.kt | 2 - 6 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/Factories.kt create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/KeyValueFromKeyValuesRepo.kt create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/Factories.kt create mode 100644 repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/KeyValuesFromKeyValueRepo.kt diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/Factories.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/Factories.kt new file mode 100644 index 00000000000..5edb5476565 --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/Factories.kt @@ -0,0 +1,12 @@ +package dev.inmo.micro_utils.repos.transforms.kv + +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.micro_utils.repos.KeyValuesRepo +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import dev.inmo.micro_utils.repos.ReadKeyValuesRepo +import kotlin.js.JsName +import kotlin.jvm.JvmName + +fun ReadKeyValuesRepo.asReadKeyValueRepo() = ReadKeyValueFromKeyValuesRepo(this) + +fun KeyValuesRepo.asKeyValueRepo() = KeyValueFromKeyValuesRepo(this) diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/KeyValueFromKeyValuesRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/KeyValueFromKeyValuesRepo.kt new file mode 100644 index 00000000000..235ceafd701 --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/KeyValueFromKeyValuesRepo.kt @@ -0,0 +1,41 @@ +package dev.inmo.micro_utils.repos.transforms.kv + +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.PaginationResult +import dev.inmo.micro_utils.pagination.changeResults +import dev.inmo.micro_utils.pagination.changeResultsUnchecked +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.pagination.utils.optionallyReverse +import dev.inmo.micro_utils.pagination.utils.paginate +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.micro_utils.repos.KeyValuesRepo +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import dev.inmo.micro_utils.repos.ReadKeyValuesRepo +import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.merge + +open class KeyValueFromKeyValuesRepo( + private val original: KeyValuesRepo +) : KeyValueRepo>, ReadKeyValueFromKeyValuesRepo(original) { + override val onNewValue: Flow>> = merge( + original.onNewValue, + original.onValueRemoved + ).mapNotNull { + it.first to (get(it.first) ?: return@mapNotNull null) + } + override val onValueRemoved: Flow = original.onDataCleared + + override suspend fun unset(toUnset: List) { + toUnset.forEach { + original.clear(it) + } + } + + override suspend fun set(toSet: Map>) { + original.set(toSet) + } +} diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt index 1f6582da2b4..9efbdd36403 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kv/ReadKeyValueFromKeyValuesRepo.kt @@ -65,5 +65,3 @@ open class ReadKeyValueFromKeyValuesRepo( } } } - -fun ReadKeyValuesRepo.asReadKeyValueRepo() = ReadKeyValueFromKeyValuesRepo(this) diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/Factories.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/Factories.kt new file mode 100644 index 00000000000..92c6abb1795 --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/Factories.kt @@ -0,0 +1,21 @@ +package dev.inmo.micro_utils.repos.transforms.kvs + +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.micro_utils.repos.ReadKeyValueRepo +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +fun > ReadKeyValueRepo.asReadKeyValuesRepo() = ReadKeyValuesFromKeyValueRepo(this) + +fun > KeyValueRepo.asKeyValuesRepo( + listToValuesIterable: suspend (List) -> VI +): KeyValuesFromKeyValueRepo = KeyValuesFromKeyValueRepo(this, listToValuesIterable) + +@JvmName("asListKeyValuesRepo") +@JsName("asListKeyValuesRepo") +fun KeyValueRepo>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo> = asKeyValuesRepo { it } + +@JvmName("asSetKeyValuesRepo") +@JsName("asSetKeyValuesRepo") +fun KeyValueRepo>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo> = asKeyValuesRepo { it.toSet() } diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/KeyValuesFromKeyValueRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/KeyValuesFromKeyValueRepo.kt new file mode 100644 index 00000000000..7473599f14f --- /dev/null +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/KeyValuesFromKeyValueRepo.kt @@ -0,0 +1,77 @@ +package dev.inmo.micro_utils.repos.transforms.kvs + +import dev.inmo.micro_utils.pagination.FirstPagePagination +import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.micro_utils.repos.KeyValuesRepo +import dev.inmo.micro_utils.repos.unset +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlin.js.JsName +import kotlin.jvm.JvmName + +open class KeyValuesFromKeyValueRepo>( + private val original: KeyValueRepo, + private val listToValuesIterable: suspend (List) -> ValuesIterable +) : KeyValuesRepo, ReadKeyValuesFromKeyValueRepo(original) { + private val _onNewValue = MutableSharedFlow>() + private val _onValueRemoved = MutableSharedFlow>() + override val onNewValue: Flow> = _onNewValue.asSharedFlow() + override val onValueRemoved: Flow> = _onValueRemoved.asSharedFlow() + override val onDataCleared: Flow = original.onValueRemoved + + override suspend fun clearWithValue(v: Value) { + val keys = mutableSetOf() + + doForAllWithNextPaging(FirstPagePagination(count().toInt())) { + original.keys(it).also { + it.results.forEach { + if (contains(it, v)) { + keys.add(it) + } + } + } + } + + original.unset(keys.toList()) + } + + override suspend fun clear(k: Key) { + original.unset(k) + } + + override suspend fun remove(toRemove: Map>) { + original.set( + toRemove.mapNotNull { (k, removing) -> + val exists = original.get(k) ?: return@mapNotNull null + k to listToValuesIterable(exists - removing).also { + if (it.firstOrNull() == null) { + original.unset(k) + return@mapNotNull null + } + } + }.toMap() + ) + toRemove.forEach { (k, v) -> + v.forEach { + _onValueRemoved.emit(k to it) + } + } + } + + override suspend fun add(toAdd: Map>) { + original.set( + toAdd.mapNotNull { (k, adding) -> + val exists = original.get(k) ?: emptyList() + k to listToValuesIterable(exists + adding) + }.toMap() + ) + toAdd.forEach { (k, v) -> + v.forEach { + _onNewValue.emit(k to it) + } + } + } + +} diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt index cb9d752f9c2..21491740076 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/transforms/kvs/ReadKeyValuesFromKeyValueRepo.kt @@ -70,5 +70,3 @@ open class ReadKeyValuesFromKeyValueRepo> ReadKeyValueRepo.asReadKeyValuesRepo() = ReadKeyValuesFromKeyValueRepo(this) From 168d6acf7c5641ca03a391dd58d3441ca2de8fd4 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 2 Feb 2023 20:05:16 +0600 Subject: [PATCH 21/25] actualizeAll now is overridable in auto recache repos --- .../repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt | 2 +- .../cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt | 2 +- .../cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt index de4a0a14acd..edca199fe97 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/crud/AutoRecacheReadCRUDRepo.kt @@ -40,7 +40,7 @@ open class AutoRecacheReadCRUDRepo( idGetter: (RegisteredObject) -> Id ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) - protected suspend fun actualizeAll(): Result { + protected open suspend fun actualizeAll(): Result { return runCatchingSafely { kvCache.actualizeAll(originalRepo) } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt index 1a46426d5e1..74711f920c0 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalue/AutoRecacheReadKeyValueRepo.kt @@ -40,7 +40,7 @@ open class AutoRecacheReadKeyValueRepo( idGetter: (RegisteredObject) -> Id ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis), idGetter) - protected suspend fun actualizeAll(): Result { + protected open suspend fun actualizeAll(): Result { return runCatchingSafely { kvCache.actualizeAll(originalRepo) } diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt index 9eec30e41c5..20b521771b2 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/fallback/keyvalues/AutoRecacheReadKeyValuesRepo.kt @@ -45,7 +45,7 @@ open class AutoRecacheReadKeyValuesRepo( recacheDelay: Long = 60.seconds.inWholeMilliseconds ) : this(originalRepo, scope, kvCache, recacheDelay, ActionWrapper.Timeouted(originalCallTimeoutMillis)) - protected suspend fun actualizeAll(): Result { + protected open suspend fun actualizeAll(): Result { return runCatchingSafely { kvCache.actualizeAll(originalRepo) } From 269c2876f358fb566bd651b6caf59b93039fcf14 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 2 Feb 2023 20:07:31 +0600 Subject: [PATCH 22/25] actualize all make it possible to disable clear on actualization --- .../repos/cache/util/ActualizeAll.kt | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt index 8eb15f14a96..61287183ff7 100644 --- a/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt +++ b/repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/util/ActualizeAll.kt @@ -11,35 +11,41 @@ import dev.inmo.micro_utils.repos.pagination.getAll import dev.inmo.micro_utils.repos.set suspend inline fun KVCache.actualizeAll( + clear: Boolean = true, getAll: () -> Map ) { set( getAll().also { - clear() + if (clear) { + clear() + } } ) } suspend inline fun KVCache.actualizeAll( - repo: ReadKeyValueRepo + repo: ReadKeyValueRepo, + clear: Boolean = true, ) { - actualizeAll { + actualizeAll(clear) { repo.getAll { keys(it) }.toMap() } } suspend inline fun KVCache>.actualizeAll( - repo: ReadKeyValuesRepo + repo: ReadKeyValuesRepo, + clear: Boolean = true, ) { - actualizeAll { + actualizeAll(clear) { repo.getAll { keys(it) }.toMap() } } suspend inline fun KVCache.actualizeAll( - repo: ReadCRUDRepo + repo: ReadCRUDRepo, + clear: Boolean = true, ) { - actualizeAll { + actualizeAll(clear) { repo.getAllByWithNextPaging { getIdsByPagination(it) }.mapNotNull { it to (repo.getById(it) ?: return@mapNotNull null) }.toMap() From f0987614c620760731b0eea58c7963a13638df2a Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 3 Feb 2023 10:07:24 +0600 Subject: [PATCH 23/25] fixes in FileKeyValueRepo --- .../kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt index d753d1f9f32..ef9ee50b713 100644 --- a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt +++ b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt @@ -31,7 +31,8 @@ class FileReadKeyValueRepo( override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult { val count = count() val resultPagination = if (reversed) pagination.reverse(count) else pagination - val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive) ?: return emptyPaginationResult() + val filesList = folder.list() + val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) ?: return emptyPaginationResult() if (reversed) { filesPaths.reverse() } @@ -44,7 +45,8 @@ class FileReadKeyValueRepo( override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult { val count = count() val resultPagination = if (reversed) pagination.reverse(count) else pagination - val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive) ?: return emptyPaginationResult() + val filesList = folder.list() + val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) ?: return emptyPaginationResult() if (reversed) { filesPaths.reverse() } From 225c06550ae8a07c4ae0c6468dcc79f7f512fc64 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 3 Feb 2023 10:23:52 +0600 Subject: [PATCH 24/25] fixes in FileKeyValueRepo --- .../micro_utils/repos/FileKeyValueRepo.kt | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt index ef9ee50b713..92909c7949f 100644 --- a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt +++ b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileKeyValueRepo.kt @@ -32,11 +32,18 @@ class FileReadKeyValueRepo( val count = count() val resultPagination = if (reversed) pagination.reverse(count) else pagination val filesList = folder.list() - val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) ?: return emptyPaginationResult() - if (reversed) { - filesPaths.reverse() + val files: Array = if (resultPagination.firstIndex < count) { + val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) + + if (reversed) { + filesPaths.reversedArray() + } else { + filesPaths + } + } else { + emptyArray() } - return filesPaths.map { File(folder, it) }.createPaginationResult( + return files.map { File(folder, it) }.createPaginationResult( resultPagination, count ) @@ -46,11 +53,20 @@ class FileReadKeyValueRepo( val count = count() val resultPagination = if (reversed) pagination.reverse(count) else pagination val filesList = folder.list() - val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) ?: return emptyPaginationResult() - if (reversed) { - filesPaths.reverse() + + val files: Array = if (resultPagination.firstIndex < count) { + val filesPaths = filesList.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive.coerceAtMost(filesList.size)) + + if (reversed) { + filesPaths.reversedArray() + } else { + filesPaths + } + } else { + emptyArray() } - return filesPaths.toList().createPaginationResult( + + return files.toList().createPaginationResult( resultPagination, count ) From 4704c5a33df73a9a362bb5ddabdbf3e431f00f9c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 4 Feb 2023 01:39:49 +0600 Subject: [PATCH 25/25] Update CHANGELOG.md --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1adb16ba77..c56303fa450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,22 @@ ## 0.16.8 +* `Versions`: + * `Ktor`: `2.2.2` -> `2.2.3` +* `Ktor`: + * `Client` + * Fixes in `HttpClient.uniUpload` + * `Server` + * Fixes in `PartData.FileItem.download` * `Repos`: * `Cache`: + * New type of caches: `FallbackCacheRepo` * Fixes in `Write*` variants of cached repos + * New type `ActionWrapper` + * New `AutoRecache*` classes for all types of repos as `FallbackCacheRepo`s + * `Common`: + * New transformations for key-value and key-values vice-verse + * Fixes in `FileReadKeyValueRepo` ## 0.16.7