Compare commits

...

15 Commits
0.2.4 ... 0.2.7

34 changed files with 246 additions and 123 deletions

View File

@@ -1,5 +1,29 @@
# Changelog # Changelog
## 0.2.7
* `Versions`:
* `Coroutines`: `1.4.0` -> `1.4.1`
* `Repos`:
* `WriteStandardKeyValueRepo` got new methods `set` and `unset` with collections
* All standard realizations of repos got collections methods realizations
* All old usages of `BroadcastFlow` and `BroadcastChannel` has been replaced with `MutableSharedFlow`
* `Ktor`:
* `Server`:
* Fixed incorrect answer for `keyvalue`
## 0.2.6
* `Pagination`
* Fixes in function `List#paginate`
* Extension property `Pagination#lastIndexExclusive`
## 0.2.5
* `Coroutines`
* Function `safelyWithoutExceptions`
* Extension `CoroutineScope#safeActor`
## 0.2.4 ## 0.2.4
* `Versions` * `Versions`

View File

@@ -17,3 +17,15 @@ fun <T> CoroutineScope.actor(
return channel return channel
} }
inline fun <T> CoroutineScope.safeActor(
channelCapacity: Int = Channel.UNLIMITED,
noinline onException: ExceptionHandler<Unit> = {},
crossinline block: suspend (T) -> Unit
): Channel<T> = actor(
channelCapacity
) {
safely(onException) {
block(it)
}
}

View File

@@ -1,7 +1,8 @@
package dev.inmo.micro_utils.coroutines package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.channels.* import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
@Suppress("FunctionName") @Suppress("FunctionName")
@Deprecated("Deprecated due to stabilization of SharedFlow and StateFlow") @Deprecated("Deprecated due to stabilization of SharedFlow and StateFlow")

View File

@@ -21,3 +21,10 @@ suspend inline fun <T> safely(
onException(e) onException(e)
} }
} }
/**
* Shortcut for [safely] without exception handler (instead of this you will receive null as a result)
*/
suspend inline fun <T> safelyWithoutExceptions(
noinline block: suspend CoroutineScope.() -> T
): T? = safely({ null }, block)

View File

@@ -5,7 +5,7 @@ kotlin.incremental=true
kotlin.incremental.js=true kotlin.incremental.js=true
kotlin_version=1.4.10 kotlin_version=1.4.10
kotlin_coroutines_version=1.4.0 kotlin_coroutines_version=1.4.1
kotlin_serialisation_core_version=1.0.1 kotlin_serialisation_core_version=1.0.1
kotlin_exposed_version=0.28.1 kotlin_exposed_version=0.28.1
@@ -19,4 +19,4 @@ github_release_plugin_version=2.2.12
uuidVersion=0.2.2 uuidVersion=0.2.2
group=dev.inmo group=dev.inmo
version=0.2.4 version=0.2.7

View File

@@ -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-6.6.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -4,7 +4,8 @@ import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.common.* import dev.inmo.micro_utils.ktor.common.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.ws import io.ktor.client.features.websocket.ws
import io.ktor.http.cio.websocket.* import io.ktor.http.cio.websocket.Frame
import io.ktor.http.cio.websocket.readBytes
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.channelFlow
import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.DeserializationStrategy

View File

@@ -4,7 +4,8 @@ import dev.inmo.micro_utils.ktor.common.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.request.post import io.ktor.client.request.post
import kotlinx.serialization.* import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerializationStrategy
typealias BodyPair<T> = Pair<SerializationStrategy<T>, T> typealias BodyPair<T> = Pair<SerializationStrategy<T>, T>

View File

@@ -22,13 +22,11 @@ fun <T> Route.includeWebsocketHandling(
converter: (T) -> StandardKtorSerialInputData converter: (T) -> StandardKtorSerialInputData
) { ) {
webSocket(suburl) { webSocket(suburl) {
// println("connected")
safely { safely {
flow.collect { flow.collect {
send(converter(it)) send(converter(it))
} }
} }
// println("disconnected")
} }
} }

View File

@@ -7,8 +7,8 @@ import io.ktor.http.HttpStatusCode
import io.ktor.request.receive import io.ktor.request.receive
import io.ktor.response.respond import io.ktor.response.respond
import io.ktor.response.respondBytes import io.ktor.response.respondBytes
import io.ktor.util.toByteArray import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.* import kotlinx.serialization.SerializationStrategy
suspend fun <T> ApplicationCall.unianswer( suspend fun <T> ApplicationCall.unianswer(
answerSerializer: SerializationStrategy<T>, answerSerializer: SerializationStrategy<T>,

View File

@@ -28,6 +28,15 @@ interface Pagination {
val Pagination.firstIndex: Int val Pagination.firstIndex: Int
get() = page * size get() = page * size
/**
* Last number in index of objects. In fact, one [Pagination] object represent data in next range:
*
* [[firstIndex], [lastIndex]]; That means, that for [Pagination] with [Pagination.size] == 10 and [Pagination.page] == 1
* you will retrieve [Pagination.firstIndex] == 10 and [Pagination.lastIndex] == 19. Here [Pagination.lastIndexExclusive] == 20
*/
val Pagination.lastIndexExclusive: Int
get() = firstIndex + size
/** /**
* Last number in index of objects. In fact, one [Pagination] object represent data in next range: * Last number in index of objects. In fact, one [Pagination] object represent data in next range:
* *
@@ -35,7 +44,7 @@ val Pagination.firstIndex: Int
* you will retrieve [Pagination.firstIndex] == 10 and [Pagination.lastIndex] == 19. * you will retrieve [Pagination.firstIndex] == 10 and [Pagination.lastIndex] == 19.
*/ */
val Pagination.lastIndex: Int val Pagination.lastIndex: Int
get() = firstIndex + size - 1 get() = lastIndexExclusive - 1
/** /**
* Calculates pages count for given [datasetSize] * Calculates pages count for given [datasetSize]

View File

@@ -21,7 +21,12 @@ fun <T> Iterable<T>.paginate(with: Pagination): PaginationResult<T> {
} }
fun <T> List<T>.paginate(with: Pagination): PaginationResult<T> { fun <T> List<T>.paginate(with: Pagination): PaginationResult<T> {
return subList(with.firstIndex, with.lastIndex + 1).createPaginationResult( val firstIndex = maxOf(with.firstIndex, 0)
val lastIndex = minOf(with.lastIndexExclusive, size)
if (firstIndex > lastIndex) {
return emptyPaginationResult()
}
return subList(firstIndex, lastIndex).createPaginationResult(
with, with,
size.toLong() size.toLong()
) )

View File

@@ -43,21 +43,13 @@ interface WriteOneToManyKeyValueRepo<Key, Value> : Repo {
val onValueRemoved: Flow<Pair<Key, Value>> val onValueRemoved: Flow<Pair<Key, Value>>
val onDataCleared: Flow<Key> val onDataCleared: Flow<Key>
suspend fun add(toAdd: Map<Key, List<Value>>) = toAdd.forEach { (k, values) -> suspend fun add(toAdd: Map<Key, List<Value>>)
values.forEach { v ->
add(k, v)
}
}
@Deprecated("Will be extracted as extension for other add method") @Deprecated("Will be extracted as extension for other add method")
suspend fun add(k: Key, v: Value) suspend fun add(k: Key, v: Value) = add(mapOf(k to listOf(v)))
suspend fun remove(toRemove: Map<Key, List<Value>>) = toRemove.forEach { (k, values) -> suspend fun remove(toRemove: Map<Key, List<Value>>)
values.forEach { v ->
remove(k, v)
}
}
@Deprecated("Will be extracted as extension for other remove method") @Deprecated("Will be extracted as extension for other remove method")
suspend fun remove(k: Key, v: Value) suspend fun remove(k: Key, v: Value) = remove(mapOf(k to listOf(v)))
suspend fun clear(k: Key) suspend fun clear(k: Key)
} }

View File

@@ -16,8 +16,16 @@ interface WriteStandardKeyValueRepo<Key, Value> : Repo {
val onNewValue: Flow<Pair<Key, Value>> val onNewValue: Flow<Pair<Key, Value>>
val onValueRemoved: Flow<Key> val onValueRemoved: Flow<Key>
@Deprecated("Realize set with map instead")
suspend fun set(k: Key, v: Value) suspend fun set(k: Key, v: Value)
suspend fun set(toSet: Map<Key, Value>) = toSet.forEach { (k, v) ->
set(k, v)
}
@Deprecated("Realize unset with list instead")
suspend fun unset(k: Key) suspend fun unset(k: Key)
suspend fun unset(toUnset: List<Key>) = toUnset.forEach {
unset(it)
}
} }
interface StandardKeyValueRepo<Key, Value> : ReadStandardKeyValueRepo<Key, Value>, WriteStandardKeyValueRepo<Key, Value> interface StandardKeyValueRepo<Key, Value> : ReadStandardKeyValueRepo<Key, Value>, WriteStandardKeyValueRepo<Key, Value>

View File

@@ -1,6 +1,5 @@
package dev.inmo.micro_utils.repos.exposed package dev.inmo.micro_utils.repos.exposed
import dev.inmo.micro_utils.repos.Repo
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
interface ExposedCRUDRepo<ObjectType, IdType> : ExposedRepo { interface ExposedCRUDRepo<ObjectType, IdType> : ExposedRepo {

View File

@@ -1,11 +1,9 @@
package dev.inmo.micro_utils.repos.exposed.keyvalue package dev.inmo.micro_utils.repos.exposed.keyvalue
import dev.inmo.micro_utils.repos.StandardKeyValueRepo import dev.inmo.micro_utils.repos.StandardKeyValueRepo
import dev.inmo.micro_utils.repos.exposed.* import dev.inmo.micro_utils.repos.exposed.ColumnAllocator
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.asFlow
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
@@ -20,11 +18,11 @@ open class ExposedKeyValueRepo<Key, Value>(
valueColumnAllocator, valueColumnAllocator,
tableName tableName
) { ) {
private val onNewValueChannel = BroadcastChannel<Pair<Key, Value>>(Channel.BUFFERED) private val _onNewValue = MutableSharedFlow<Pair<Key, Value>>(Channel.BUFFERED)
private val onValueRemovedChannel = BroadcastChannel<Key>(Channel.BUFFERED) private val _onValueRemoved = MutableSharedFlow<Key>(Channel.BUFFERED)
override val onNewValue: Flow<Pair<Key, Value>> = onNewValueChannel.asFlow() override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow()
override val onValueRemoved: Flow<Key> = onValueRemovedChannel.asFlow() override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow()
override suspend fun set(k: Key, v: Value) { override suspend fun set(k: Key, v: Value) {
transaction(database) { transaction(database) {
@@ -39,14 +37,50 @@ open class ExposedKeyValueRepo<Key, Value>(
} }
} }
} }
onNewValueChannel.send(k to v) _onNewValue.emit(k to v)
}
override suspend fun set(toSet: Map<Key, Value>) {
transaction(database) {
toSet.mapNotNull { (k, v) ->
if (update({ keyColumn.eq(k) }) { it[valueColumn] = v } > 0) {
k to v
} else {
val inserted = insert {
it[keyColumn] = k
it[valueColumn] = v
}.getOrNull(keyColumn) != null
if (inserted) {
k to v
} else {
null
}
}
}
}.forEach {
_onNewValue.emit(it)
}
} }
override suspend fun unset(k: Key) { override suspend fun unset(k: Key) {
transaction(database) { transaction(database) {
deleteWhere { keyColumn.eq(k) } deleteWhere { keyColumn.eq(k) }
} }
onValueRemovedChannel.send(k) _onValueRemoved.emit(k)
}
override suspend fun unset(toUnset: List<Key>) {
transaction(database) {
toUnset.mapNotNull {
if (deleteWhere { keyColumn.eq(it) } > 0) {
it
} else {
null
}
}
}.forEach {
_onValueRemoved.emit(it)
}
} }
} }

View File

@@ -2,7 +2,8 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
import dev.inmo.micro_utils.repos.exposed.* import dev.inmo.micro_utils.repos.exposed.ColumnAllocator
import dev.inmo.micro_utils.repos.exposed.ExposedRepo
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction

View File

@@ -3,8 +3,7 @@ package dev.inmo.micro_utils.repos.exposed.onetomany
import dev.inmo.micro_utils.coroutines.BroadcastFlow import dev.inmo.micro_utils.coroutines.BroadcastFlow
import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo
import dev.inmo.micro_utils.repos.exposed.ColumnAllocator import dev.inmo.micro_utils.repos.exposed.ColumnAllocator
import dev.inmo.micro_utils.repos.exposed.initTable import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.Flow
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
@@ -19,13 +18,13 @@ open class ExposedOneToManyKeyValueRepo<Key, Value>(
valueColumnAllocator, valueColumnAllocator,
tableName tableName
) { ) {
protected val _onNewValue: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow() protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow()
override val onNewValue: Flow<Pair<Key, Value>> override val onNewValue: Flow<Pair<Key, Value>>
get() = _onNewValue get() = _onNewValue
protected val _onValueRemoved: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow() protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow()
override val onValueRemoved: Flow<Pair<Key, Value>> override val onValueRemoved: Flow<Pair<Key, Value>>
get() = _onValueRemoved get() = _onValueRemoved
protected val _onDataCleared: BroadcastFlow<Key> = BroadcastFlow() protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow()
override val onDataCleared: Flow<Key> override val onDataCleared: Flow<Key>
get() = _onDataCleared get() = _onDataCleared
@@ -35,19 +34,42 @@ open class ExposedOneToManyKeyValueRepo<Key, Value>(
it[keyColumn] = k it[keyColumn] = k
it[valueColumn] = v it[valueColumn] = v
} }
}.also { _onNewValue.send(k to v) } }.also { _onNewValue.emit(k to v) }
} }
override suspend fun remove(k: Key, v: Value) { override suspend fun add(toAdd: Map<Key, List<Value>>) {
transaction(database) { transaction(database) {
deleteWhere { keyColumn.eq(k).and(valueColumn.eq(v)) } toAdd.keys.flatMap { k ->
}.also { _onValueRemoved.send(k to v) } toAdd[k] ?.mapNotNull { v ->
insertIgnore {
it[keyColumn] = k
it[valueColumn] = v
}.getOrNull(keyColumn) ?.let { k to v }
} ?: emptyList()
}
}.forEach { _onNewValue.emit(it) }
}
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
transaction(database) {
toRemove.keys.flatMap { k ->
toRemove[k] ?.mapNotNull { v ->
if (deleteIgnoreWhere { keyColumn.eq(k).and(valueColumn.eq(v)) } > 0 ) {
k to v
} else {
null
}
} ?: emptyList()
}
}.forEach {
_onValueRemoved.emit(it)
}
} }
override suspend fun clear(k: Key) { override suspend fun clear(k: Key) {
transaction(database) { transaction(database) {
deleteWhere { keyColumn.eq(k) } deleteWhere { keyColumn.eq(k) }
}.also { _onDataCleared.send(k) } }.also { _onDataCleared.emit(k) }
} }
} }

View File

@@ -1,10 +1,12 @@
package dev.inmo.micro_utils.repos package dev.inmo.micro_utils.repos
import dev.inmo.micro_utils.coroutines.BroadcastFlow import dev.inmo.micro_utils.coroutines.BroadcastFlow
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.pagination.utils.paginate import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.pagination.utils.reverse import dev.inmo.micro_utils.pagination.utils.reverse
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
class ReadMapKeyValueRepo<Key, Value>( class ReadMapKeyValueRepo<Key, Value>(
private val map: Map<Key, Value> = emptyMap() private val map: Map<Key, Value> = emptyMap()
@@ -46,20 +48,31 @@ class ReadMapKeyValueRepo<Key, Value>(
class WriteMapKeyValueRepo<Key, Value>( class WriteMapKeyValueRepo<Key, Value>(
private val map: MutableMap<Key, Value> = mutableMapOf() private val map: MutableMap<Key, Value> = mutableMapOf()
) : WriteStandardKeyValueRepo<Key, Value> { ) : WriteStandardKeyValueRepo<Key, Value> {
private val _onNewValue: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow() private val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow()
override val onNewValue: Flow<Pair<Key, Value>> override val onNewValue: Flow<Pair<Key, Value>>
get() = _onNewValue get() = _onNewValue
private val _onValueRemoved: BroadcastFlow<Key> = BroadcastFlow() private val _onValueRemoved: MutableSharedFlow<Key> = MutableSharedFlow()
override val onValueRemoved: Flow<Key> override val onValueRemoved: Flow<Key>
get() = _onValueRemoved get() = _onValueRemoved
override suspend fun set(k: Key, v: Value) { override suspend fun set(k: Key, v: Value) {
map[k] = v map[k] = v
_onNewValue.send(k to v) _onNewValue.emit(k to v)
}
override suspend fun set(toSet: Map<Key, Value>) {
map.putAll(toSet)
toSet.forEach { (k, v) -> _onNewValue.emit(k to v) }
} }
override suspend fun unset(k: Key) { override suspend fun unset(k: Key) {
map.remove(k) ?.also { _onValueRemoved.send(k) } map.remove(k) ?.also { _onValueRemoved.emit(k) }
}
override suspend fun unset(toUnset: List<Key>) {
toUnset.forEach { k ->
map.remove(k) ?.also { _ -> _onValueRemoved.emit(k) }
}
} }
} }

View File

@@ -55,13 +55,18 @@ class MapWriteOneToManyKeyValueRepo<Key, Value>(
override val onDataCleared: Flow<Key> override val onDataCleared: Flow<Key>
get() = _onDataCleared get() = _onDataCleared
override suspend fun add(k: Key, v: Value) { override suspend fun add(toAdd: Map<Key, List<Value>>) {
map.getOrPut(k) { mutableListOf() }.add(v) toAdd.keys.forEach {
_onNewValue.send(k to v) map.getOrPut(it) {
mutableListOf()
}.addAll(toAdd[it] ?: return@forEach)
}
} }
override suspend fun remove(k: Key, v: Value) { override suspend fun remove(toRemove: Map<Key, List<Value>>) {
map[k] ?.remove(v) ?.also { _onValueRemoved.send(k to v) } toRemove.keys.forEach {
map[it] ?.removeAll(toRemove[it] ?: return@forEach)
}
} }
override suspend fun clear(k: Key) { override suspend fun clear(k: Key) {

View File

@@ -3,9 +3,7 @@ package dev.inmo.micro_utils.repos.ktor.client.crud
import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue
import dev.inmo.micro_utils.ktor.client.uniget import dev.inmo.micro_utils.ktor.client.uniget
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
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.asUrlQueryParts
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
import dev.inmo.micro_utils.repos.ktor.common.crud.* import dev.inmo.micro_utils.repos.ktor.common.crud.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient

View File

@@ -1,8 +1,6 @@
package dev.inmo.micro_utils.repos.ktor.client.crud package dev.inmo.micro_utils.repos.ktor.client.crud
import dev.inmo.micro_utils.ktor.client.BodyPair import dev.inmo.micro_utils.ktor.client.*
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
import dev.inmo.micro_utils.ktor.client.unipost
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.repos.UpdatedValuePair import dev.inmo.micro_utils.repos.UpdatedValuePair
import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo

View File

@@ -3,12 +3,10 @@ package dev.inmo.micro_utils.repos.ktor.client.key_value
import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue
import dev.inmo.micro_utils.ktor.client.uniget import dev.inmo.micro_utils.ktor.client.uniget
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
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.asUrlQueryParts
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.key_value.* import dev.inmo.micro_utils.repos.ktor.common.key_value.*
import io.ktor.client.* import io.ktor.client.HttpClient
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer

View File

@@ -1,9 +1,7 @@
package dev.inmo.micro_utils.repos.ktor.client.key_value package dev.inmo.micro_utils.repos.ktor.client.key_value
import dev.inmo.micro_utils.repos.StandardKeyValueRepo import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo import io.ktor.client.HttpClient
import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo
import io.ktor.client.*
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
class KtorStandartKeyValueRepo<K, V> ( class KtorStandartKeyValueRepo<K, V> (

View File

@@ -1,16 +1,13 @@
package dev.inmo.micro_utils.repos.ktor.client.key_value package dev.inmo.micro_utils.repos.ktor.client.key_value
import dev.inmo.micro_utils.ktor.client.BodyPair import dev.inmo.micro_utils.ktor.client.*
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
import dev.inmo.micro_utils.ktor.client.unipost
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.key_value.* import dev.inmo.micro_utils.repos.ktor.common.key_value.*
import io.ktor.client.* import io.ktor.client.HttpClient
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer import kotlinx.serialization.builtins.*
import kotlinx.serialization.builtins.serializer
class KtorWriteStandardKeyValueRepo<K, V> ( class KtorWriteStandardKeyValueRepo<K, V> (
private var baseUrl: String, private var baseUrl: String,
@@ -18,6 +15,8 @@ class KtorWriteStandardKeyValueRepo<K, V> (
private var keySerializer: KSerializer<K>, private var keySerializer: KSerializer<K>,
private var valueSerializer: KSerializer<V>, private var valueSerializer: KSerializer<V>,
) : WriteStandardKeyValueRepo<K, V> { ) : WriteStandardKeyValueRepo<K, V> {
private val keyValueMapSerializer = MapSerializer(keySerializer, valueSerializer)
private val keysListSerializer = ListSerializer(keySerializer)
override val onNewValue: Flow<Pair<K, V>> = client.createStandardWebsocketFlow( override val onNewValue: Flow<Pair<K, V>> = client.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute), buildStandardUrl(baseUrl, onNewValueRoute),
deserializer = PairSerializer(keySerializer, valueSerializer) deserializer = PairSerializer(keySerializer, valueSerializer)
@@ -28,23 +27,25 @@ class KtorWriteStandardKeyValueRepo<K, V> (
deserializer = keySerializer deserializer = keySerializer
) )
override suspend fun set(k: K, v: V) = client.unipost( override suspend fun set(toSet: Map<K, V>) = client.unipost(
buildStandardUrl( buildStandardUrl(
baseUrl, baseUrl,
setRoute setRoute
), ),
BodyPair(KeyValuePostObject.serializer(keySerializer, valueSerializer), KeyValuePostObject(k, v)), BodyPair(keyValueMapSerializer, toSet),
Unit.serializer() Unit.serializer()
) )
override suspend fun set(k: K, v: V) = set(mapOf(k to v))
override suspend fun unset(k: K) = client.unipost( override suspend fun unset(toUnset: List<K>) = client.unipost(
buildStandardUrl( buildStandardUrl(
baseUrl, baseUrl,
unsetRoute, unsetRoute,
), ),
BodyPair(keySerializer, k), BodyPair(keysListSerializer, toUnset),
Unit.serializer() Unit.serializer()
) )
override suspend fun unset(k: K) = unset(listOf(k))
} }
@Deprecated("Renamed", ReplaceWith("KtorWriteStandardKeyValueRepo", "dev.inmo.micro_utils.repos.ktor.client.key_value.KtorWriteStandardKeyValueRepo")) @Deprecated("Renamed", ReplaceWith("KtorWriteStandardKeyValueRepo", "dev.inmo.micro_utils.repos.ktor.client.key_value.KtorWriteStandardKeyValueRepo"))

View File

@@ -1,8 +1,6 @@
package dev.inmo.micro_utils.repos.ktor.client.one_to_many package dev.inmo.micro_utils.repos.ktor.client.one_to_many
import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
import dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer

View File

@@ -3,9 +3,7 @@ package dev.inmo.micro_utils.repos.ktor.client.one_to_many
import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue import dev.inmo.micro_utils.ktor.client.encodeUrlQueryValue
import dev.inmo.micro_utils.ktor.client.uniget import dev.inmo.micro_utils.ktor.client.uniget
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
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.asUrlQueryParts
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.* import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient

View File

@@ -1,16 +1,13 @@
package dev.inmo.micro_utils.repos.ktor.client.one_to_many package dev.inmo.micro_utils.repos.ktor.client.one_to_many
import dev.inmo.micro_utils.coroutines.broadcastStateFlow
import dev.inmo.micro_utils.ktor.client.* import dev.inmo.micro_utils.ktor.client.*
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo import dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.* import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer import kotlinx.serialization.builtins.*
import kotlinx.serialization.builtins.serializer
class KtorWriteOneToManyKeyValueRepo<Key, Value> ( class KtorWriteOneToManyKeyValueRepo<Key, Value> (
private val baseUrl: String, private val baseUrl: String,
@@ -19,6 +16,7 @@ class KtorWriteOneToManyKeyValueRepo<Key, Value> (
private val valueSerializer: KSerializer<Value> private val valueSerializer: KSerializer<Value>
) : WriteOneToManyKeyValueRepo<Key, Value> { ) : WriteOneToManyKeyValueRepo<Key, Value> {
private val keyValueSerializer = PairSerializer(keySerializer, valueSerializer) private val keyValueSerializer = PairSerializer(keySerializer, valueSerializer)
private val keyValueMapSerializer = MapSerializer(keySerializer, ListSerializer(valueSerializer))
override val onNewValue: Flow<Pair<Key, Value>> = client.createStandardWebsocketFlow( override val onNewValue: Flow<Pair<Key, Value>> = client.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute), buildStandardUrl(baseUrl, onNewValueRoute),
deserializer = keyValueSerializer deserializer = keyValueSerializer
@@ -41,15 +39,23 @@ class KtorWriteOneToManyKeyValueRepo<Key, Value> (
Unit.serializer(), Unit.serializer(),
) )
override suspend fun remove(k: Key, v: Value) = client.unipost( override suspend fun remove(toRemove: Map<Key, List<Value>>) = client.unipost(
buildStandardUrl( buildStandardUrl(
baseUrl, baseUrl,
removeRoute, removeRoute,
), ),
BodyPair(keyValueSerializer, k to v), BodyPair(keyValueMapSerializer, toRemove),
Unit.serializer(), Unit.serializer(),
) )
override suspend fun add(toAdd: Map<Key, List<Value>>) = client.unipost(
buildStandardUrl(
baseUrl,
clearRoute,
),
BodyPair(keyValueMapSerializer, toAdd),
Unit.serializer(),
)
override suspend fun clear(k: Key) = client.unipost( override suspend fun clear(k: Key) = client.unipost(
buildStandardUrl( buildStandardUrl(
baseUrl, baseUrl,

View File

@@ -1,8 +1,6 @@
package dev.inmo.micro_utils.repos.ktor.server.crud package dev.inmo.micro_utils.repos.ktor.server.crud
import dev.inmo.micro_utils.ktor.server.includeWebsocketHandling import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.unianswer
import dev.inmo.micro_utils.ktor.server.uniload
import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo
import dev.inmo.micro_utils.repos.ktor.common.crud.* import dev.inmo.micro_utils.repos.ktor.common.crud.*
import io.ktor.application.call import io.ktor.application.call

View File

@@ -1,7 +1,8 @@
package dev.inmo.micro_utils.repos.ktor.server.key_value package dev.inmo.micro_utils.repos.ktor.server.key_value
import dev.inmo.micro_utils.repos.StandardKeyValueRepo import dev.inmo.micro_utils.repos.StandardKeyValueRepo
import io.ktor.routing.* import io.ktor.routing.Route
import io.ktor.routing.route
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
fun <K, V> Route.configureStandartKeyValueRepoRoutes( fun <K, V> Route.configureStandartKeyValueRepoRoutes(

View File

@@ -6,8 +6,9 @@ import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.pagination.extractPagination import dev.inmo.micro_utils.pagination.extractPagination
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.key_value.* import dev.inmo.micro_utils.repos.ktor.common.key_value.*
import io.ktor.application.* import io.ktor.application.call
import io.ktor.routing.* import io.ktor.routing.Route
import io.ktor.routing.get
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer

View File

@@ -1,19 +1,21 @@
package dev.inmo.micro_utils.repos.ktor.server.key_value package dev.inmo.micro_utils.repos.ktor.server.key_value
import dev.inmo.micro_utils.ktor.server.includeWebsocketHandling import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.uniload
import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo
import dev.inmo.micro_utils.repos.ktor.common.key_value.* import dev.inmo.micro_utils.repos.ktor.common.key_value.*
import io.ktor.application.* import io.ktor.application.call
import io.ktor.routing.* import io.ktor.routing.Route
import io.ktor.routing.post
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer import kotlinx.serialization.builtins.*
fun <K, V> Route.configureWriteStandartKeyValueRepoRoutes ( fun <K, V> Route.configureWriteStandartKeyValueRepoRoutes (
originalRepo: WriteStandardKeyValueRepo<K, V>, originalRepo: WriteStandardKeyValueRepo<K, V>,
keySerializer: KSerializer<K>, keySerializer: KSerializer<K>,
valueSerializer: KSerializer<V>, valueSerializer: KSerializer<V>,
) { ) {
val keyValueMapSerializer = MapSerializer(keySerializer, valueSerializer)
val keysListSerializer = ListSerializer(keySerializer)
includeWebsocketHandling( includeWebsocketHandling(
onNewValueRoute, onNewValueRoute,
originalRepo.onNewValue, originalRepo.onNewValue,
@@ -27,18 +29,16 @@ fun <K, V> Route.configureWriteStandartKeyValueRepoRoutes (
) )
post(setRoute) { post(setRoute) {
val (key, value) = call.uniload( val toSet = call.uniload(
KeyValuePostObject.serializer(keySerializer, valueSerializer) keyValueMapSerializer
) )
originalRepo.set(key, value) call.unianswer(Unit.serializer(), originalRepo.set(toSet))
} }
post(unsetRoute) { post(unsetRoute) {
val key = call.uniload( val toUnset = call.uniload(keysListSerializer)
keySerializer
)
originalRepo.unset(key) call.unianswer(Unit.serializer(), originalRepo.unset(toUnset))
} }
} }

View File

@@ -1,8 +1,6 @@
package dev.inmo.micro_utils.repos.ktor.server.one_to_many package dev.inmo.micro_utils.repos.ktor.server.one_to_many
import dev.inmo.micro_utils.ktor.server.decodeUrlQueryValue import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.decodeUrlQueryValueOrSendError
import dev.inmo.micro_utils.ktor.server.unianswer
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.pagination.extractPagination import dev.inmo.micro_utils.pagination.extractPagination
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo

View File

@@ -7,15 +7,15 @@ import io.ktor.application.call
import io.ktor.routing.Route import io.ktor.routing.Route
import io.ktor.routing.post import io.ktor.routing.post
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer import kotlinx.serialization.builtins.*
import kotlinx.serialization.builtins.serializer
fun <Key, Value> Route.configureOneToManyWriteKeyValueRepoRoutes( fun <Key, Value> Route.configureOneToManyWriteKeyValueRepoRoutes(
originalRepo: WriteOneToManyKeyValueRepo<Key, Value>, originalRepo: WriteOneToManyKeyValueRepo<Key, Value>,
keySerializer: KSerializer<Key>, keySerializer: KSerializer<Key>,
valueSealizer: KSerializer<Value>, valueSerializer: KSerializer<Value>,
) { ) {
val keyValueSerializer = PairSerializer(keySerializer, valueSealizer) val keyValueSerializer = PairSerializer(keySerializer, valueSerializer)
val keyValueMapSerializer = MapSerializer(keySerializer, ListSerializer(valueSerializer))
includeWebsocketHandling( includeWebsocketHandling(
onNewValueRoute, onNewValueRoute,
@@ -34,24 +34,22 @@ fun <Key, Value> Route.configureOneToManyWriteKeyValueRepoRoutes(
) )
post(addRoute) { post(addRoute) {
val obj = call.uniload( val obj = call.uniload(keyValueMapSerializer)
keyValueSerializer
)
call.unianswer( call.unianswer(
Unit.serializer(), Unit.serializer(),
originalRepo.add(obj.first, obj.second) originalRepo.add(obj)
) )
} }
post(removeRoute) { post(removeRoute) {
val obj = call.uniload( val obj = call.uniload(
keyValueSerializer keyValueMapSerializer
) )
call.unianswer( call.unianswer(
Unit.serializer(), Unit.serializer(),
originalRepo.remove(obj.first, obj.second), originalRepo.remove(obj),
) )
} }