mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-18 06:49:20 +00:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
44317d1519 | |||
48e08fcc69 | |||
1a3ce6e623 | |||
fb122f3e70 | |||
7cca6039cc | |||
118e3dba39 | |||
87070710fa | |||
38499c3d4a | |||
5d754d968b | |||
d543d436bc | |||
12b54f99af | |||
2a95d7e643 | |||
e3d3cacfa4 | |||
4b13491a0e | |||
85d516d1e9 | |||
ac58b6a7e3 | |||
2cc6126765 | |||
f94b085850 | |||
c9822a491b | |||
23b2d60295 | |||
f4bc9eed39 | |||
e310f188b0 | |||
6c1571188c | |||
945d2fa284 |
44
CHANGELOG.md
44
CHANGELOG.md
@@ -1,5 +1,49 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.12.11
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* Override `KeyValue` cache method `values`
|
||||||
|
|
||||||
|
## 0.12.10
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* Hotfix in key values `get`
|
||||||
|
|
||||||
|
## 0.12.9
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Klock`: `3.0.0` -> `3.1.0`
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* Fixes in key values cache
|
||||||
|
|
||||||
|
## 0.12.8
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Ktor`: `2.1.0` -> `2.1.1`
|
||||||
|
* `Compose`: `1.2.0-alpha01-dev764` -> `1.2.0-alpha01-dev774`
|
||||||
|
* `Ktor`:
|
||||||
|
* `Client`:
|
||||||
|
* New extension `HttpClient#bodyOrNull` which returns `null` in case when server responded with `No Content` (204)
|
||||||
|
* `Server`:
|
||||||
|
* New extension `ApplicationCall#respondOrNoContent` which responds `No Content` (204) when passed data is null
|
||||||
|
|
||||||
|
## 0.12.7
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* Force `WriteCRUDCacheRepo` to subscribe on new and updated objects of parent repo
|
||||||
|
* `Pagination`:
|
||||||
|
* New function `changeResultsUnchecked(Pagination)`
|
||||||
|
|
||||||
|
## 0.12.6
|
||||||
|
|
||||||
|
* `MimeeTypes>`:
|
||||||
|
* Fixed absence of `image/*` in known mime types
|
||||||
|
|
||||||
## 0.12.5
|
## 0.12.5
|
||||||
|
|
||||||
* `Repos`:
|
* `Repos`:
|
||||||
|
@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.12.5
|
version=0.12.11
|
||||||
android_code_version=144
|
android_code_version=150
|
||||||
|
@@ -4,14 +4,14 @@ kt = "1.7.10"
|
|||||||
kt-serialization = "1.4.0"
|
kt-serialization = "1.4.0"
|
||||||
kt-coroutines = "1.6.4"
|
kt-coroutines = "1.6.4"
|
||||||
|
|
||||||
jb-compose = "1.2.0-alpha01-dev764"
|
jb-compose = "1.2.0-alpha01-dev774"
|
||||||
jb-exposed = "0.39.2"
|
jb-exposed = "0.39.2"
|
||||||
jb-dokka = "1.7.10"
|
jb-dokka = "1.7.10"
|
||||||
|
|
||||||
klock = "3.0.0"
|
klock = "3.1.0"
|
||||||
uuid = "0.5.0"
|
uuid = "0.5.0"
|
||||||
|
|
||||||
ktor = "2.1.0"
|
ktor = "2.1.1"
|
||||||
|
|
||||||
gh-release = "2.4.1"
|
gh-release = "2.4.1"
|
||||||
|
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
package dev.inmo.micro_utils.ktor.client
|
||||||
|
|
||||||
|
import io.ktor.client.call.body
|
||||||
|
import io.ktor.client.statement.HttpResponse
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
|
||||||
|
suspend inline fun <reified T : Any> HttpResponse.bodyOrNull() = takeIf {
|
||||||
|
status == HttpStatusCode.OK
|
||||||
|
} ?.body<T>()
|
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.micro_utils.ktor.server
|
||||||
|
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.server.application.ApplicationCall
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
|
||||||
|
suspend inline fun <reified T : Any> ApplicationCall.respondOrNoContent(
|
||||||
|
data: T?
|
||||||
|
) {
|
||||||
|
if (data == null) {
|
||||||
|
respond(HttpStatusCode.NoContent)
|
||||||
|
} else {
|
||||||
|
respond(data)
|
||||||
|
}
|
||||||
|
}
|
@@ -2017,6 +2017,7 @@ internal val knownMimeTypes: Set<MimeType> = setOf(
|
|||||||
KnownMimeTypes.Chemical.XCml,
|
KnownMimeTypes.Chemical.XCml,
|
||||||
KnownMimeTypes.Chemical.XCsml,
|
KnownMimeTypes.Chemical.XCsml,
|
||||||
KnownMimeTypes.Chemical.XXyz,
|
KnownMimeTypes.Chemical.XXyz,
|
||||||
|
KnownMimeTypes.Image.Any,
|
||||||
KnownMimeTypes.Image.Bmp,
|
KnownMimeTypes.Image.Bmp,
|
||||||
KnownMimeTypes.Image.Cgm,
|
KnownMimeTypes.Image.Cgm,
|
||||||
KnownMimeTypes.Image.G3fax,
|
KnownMimeTypes.Image.G3fax,
|
||||||
|
@@ -48,6 +48,14 @@ data class PaginationResult<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L)
|
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L)
|
||||||
|
fun <T> emptyPaginationResult(
|
||||||
|
basePagination: Pagination
|
||||||
|
) = PaginationResult<T>(
|
||||||
|
basePagination.page,
|
||||||
|
basePagination.size,
|
||||||
|
emptyList(),
|
||||||
|
0L
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return New [PaginationResult] with [data] without checking of data sizes equality
|
* @return New [PaginationResult] with [data] without checking of data sizes equality
|
||||||
|
@@ -33,6 +33,14 @@ open class WriteCRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
|||||||
override val updatedObjectsFlow: Flow<ObjectType> by parentRepo::updatedObjectsFlow
|
override val updatedObjectsFlow: Flow<ObjectType> by parentRepo::updatedObjectsFlow
|
||||||
override val deletedObjectsIdsFlow: Flow<IdType> by parentRepo::deletedObjectsIdsFlow
|
override val deletedObjectsIdsFlow: Flow<IdType> by parentRepo::deletedObjectsIdsFlow
|
||||||
|
|
||||||
|
val createdObjectsFlowJob = parentRepo.newObjectsFlow.onEach {
|
||||||
|
kvCache.set(idGetter(it), it)
|
||||||
|
}.launchIn(scope)
|
||||||
|
|
||||||
|
val updatedObjectsFlowJob = parentRepo.updatedObjectsFlow.onEach {
|
||||||
|
kvCache.set(idGetter(it), it)
|
||||||
|
}.launchIn(scope)
|
||||||
|
|
||||||
val deletedObjectsFlowJob = parentRepo.deletedObjectsIdsFlow.onEach {
|
val deletedObjectsFlowJob = parentRepo.deletedObjectsIdsFlow.onEach {
|
||||||
kvCache.unset(it)
|
kvCache.unset(it)
|
||||||
}.launchIn(scope)
|
}.launchIn(scope)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package dev.inmo.micro_utils.repos.cache
|
package dev.inmo.micro_utils.repos.cache
|
||||||
|
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -14,6 +13,16 @@ open class ReadKeyValueCacheRepo<Key,Value>(
|
|||||||
) : ReadKeyValueRepo<Key,Value> by parentRepo, CacheRepo {
|
) : ReadKeyValueRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
override suspend fun get(k: Key): Value? = kvCache.get(k) ?: parentRepo.get(k) ?.also { kvCache.set(k, it) }
|
override suspend fun get(k: Key): Value? = kvCache.get(k) ?: parentRepo.get(k) ?.also { kvCache.set(k, it) }
|
||||||
override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key)
|
override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key)
|
||||||
|
|
||||||
|
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
||||||
|
return keys(pagination, reversed).let {
|
||||||
|
it.changeResultsUnchecked(
|
||||||
|
it.results.mapNotNull {
|
||||||
|
get(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
|
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
package dev.inmo.micro_utils.repos.cache
|
package dev.inmo.micro_utils.repos.cache
|
||||||
|
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
import dev.inmo.micro_utils.pagination.utils.*
|
||||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
|
||||||
import dev.inmo.micro_utils.pagination.utils.reverse
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -15,18 +13,22 @@ open class ReadKeyValuesCacheRepo<Key,Value>(
|
|||||||
protected open val kvCache: KVCache<Key, List<Value>>
|
protected open val kvCache: KVCache<Key, List<Value>>
|
||||||
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
||||||
return kvCache.get(k) ?.paginate(
|
return getAll(k, reversed).paginate(
|
||||||
pagination.let { if (reversed) it.reverse(count(k)) else it }
|
pagination
|
||||||
) ?.let {
|
)
|
||||||
if (reversed) it.copy(results = it.results.reversed()) else it
|
|
||||||
} ?: parentRepo.get(k, pagination, reversed)
|
|
||||||
}
|
}
|
||||||
override suspend fun getAll(k: Key, reversed: Boolean): List<Value> {
|
override suspend fun getAll(k: Key, reversed: Boolean): List<Value> {
|
||||||
return kvCache.get(k) ?.let {
|
return kvCache.get(k) ?.let {
|
||||||
if (reversed) it.reversed() else it
|
if (reversed) it.reversed() else it
|
||||||
} ?: parentRepo.getAll(k, reversed)
|
} ?: parentRepo.getAll(k, reversed).also {
|
||||||
|
kvCache.set(k, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
override suspend fun contains(k: Key, v: Value): Boolean = kvCache.get(k) ?.contains(v) ?: parentRepo.contains(k, v)
|
override suspend fun contains(k: Key, v: Value): Boolean = kvCache.get(k) ?.contains(v) ?: (parentRepo.contains(k, v).also {
|
||||||
|
if (it) {
|
||||||
|
kvCache.unset(k) // clear as invalid
|
||||||
|
}
|
||||||
|
})
|
||||||
override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
|
override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,9 +41,21 @@ open class KeyValuesCacheRepo<Key,Value>(
|
|||||||
kvCache: KVCache<Key, List<Value>>,
|
kvCache: KVCache<Key, List<Value>>,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.plus(it.second) ?: listOf(it.second)) }.launchIn(scope)
|
protected val onNewJob = parentRepo.onNewValue.onEach { (k, v) ->
|
||||||
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.minus(it.second) ?: return@onEach) }.launchIn(scope)
|
kvCache.set(
|
||||||
protected val onDataClearedJob = parentRepo.onDataCleared.onEach { kvCache.unset(it) }.launchIn(scope)
|
k,
|
||||||
|
kvCache.get(k) ?.plus(v) ?: return@onEach
|
||||||
|
)
|
||||||
|
}.launchIn(scope)
|
||||||
|
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { (k, v) ->
|
||||||
|
kvCache.set(
|
||||||
|
k,
|
||||||
|
kvCache.get(k) ?.minus(v) ?: return@onEach
|
||||||
|
)
|
||||||
|
}.launchIn(scope)
|
||||||
|
protected val onDataClearedJob = parentRepo.onDataCleared.onEach {
|
||||||
|
kvCache.unset(it)
|
||||||
|
}.launchIn(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <Key, Value> KeyValuesRepo<Key, Value>.cached(
|
fun <Key, Value> KeyValuesRepo<Key, Value>.cached(
|
||||||
|
@@ -25,6 +25,9 @@ open class SimpleKVCache<K, V>(
|
|||||||
kvParent.unset(it)
|
kvParent.unset(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
val removed = cacheQueue.remove(k)
|
||||||
|
} while (removed)
|
||||||
cacheQueue.addLast(k)
|
cacheQueue.addLast(k)
|
||||||
kvParent.set(k, v)
|
kvParent.set(k, v)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user