impl client and server for KeyValueRepo

This commit is contained in:
000Sanya 2020-08-29 12:33:13 +10:00
parent 00068a064f
commit cb6fedfb52
9 changed files with 324 additions and 0 deletions

View File

@ -0,0 +1,30 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.key_value
import com.insanusmokrassar.postssystem.utils.repos.StandardKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.StandardWriteKeyValueRepo
import io.ktor.client.*
import kotlinx.serialization.ContextualSerializer
import kotlinx.serialization.KSerializer
class KtorStandartKeyValueRepo<K, V> (
baseUrl: String,
baseSubpart: String,
client: HttpClient = HttpClient(),
keySerializer: KSerializer<K>,
valueSerializer: KSerializer<V>,
valueNullableSerializer: KSerializer<V?>
) : StandardKeyValueRepo<K, V>,
StandardReadKeyValueRepo<K, V> by KtorStandartReadKeyValueRepo(
"$baseUrl/$baseSubpart",
client,
keySerializer,
valueSerializer,
valueNullableSerializer
),
StandardWriteKeyValueRepo<K, V> by KtorStandartWriteKeyValueRepo(
"$baseUrl/$baseSubpart",
client,
keySerializer,
valueSerializer
)

View File

@ -0,0 +1,73 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.key_value
import com.insanusmokrassar.postssystem.ktor.asUrlQueryParts
import com.insanusmokrassar.postssystem.ktor.buildStandardUrl
import com.insanusmokrassar.postssystem.ktor.client.uniget
import com.insanusmokrassar.postssystem.ktor.toHex
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value.*
import io.ktor.client.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
class KtorStandartReadKeyValueRepo<Key, Value> (
private var baseUrl: String,
private var client: HttpClient = HttpClient(),
private var keySerializer: KSerializer<Key>,
private var valueSerializer: KSerializer<Value>,
private var valueNullableSerializer: KSerializer<Value?>,
) : StandardReadKeyValueRepo<Key, Value> {
override suspend fun get(k: Key): Value? = client.uniget(
buildStandardUrl(
baseUrl,
getRoute,
mapOf(
keyParameterName to k.toHex(keySerializer)
)
),
valueNullableSerializer
)
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = client.uniget(
buildStandardUrl(
baseUrl,
valuesRoute,
mapOf(
reversedParameterName to reversed.toHex(Boolean.serializer())
) + pagination.asUrlQueryParts
),
PaginationResult.serializer(valueSerializer)
)
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = client.uniget(
buildStandardUrl(
baseUrl,
keysRoute,
mapOf(
reversedParameterName to reversed.toHex(Boolean.serializer())
) + pagination.asUrlQueryParts
),
PaginationResult.serializer(keySerializer)
)
override suspend fun contains(key: Key): Boolean = client.uniget(
buildStandardUrl(
baseUrl,
containsRoute,
mapOf(
keyParameterName to key.toHex(keySerializer)
),
),
Boolean.serializer(),
)
override suspend fun count(): Long = client.uniget(
buildStandardUrl(
baseUrl,
containsRoute,
),
Long.serializer()
)
}

View File

@ -0,0 +1,49 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.client.key_value
import com.insanusmokrassar.postssystem.ktor.buildStandardUrl
import com.insanusmokrassar.postssystem.ktor.client.BodyPair
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
import com.insanusmokrassar.postssystem.ktor.client.uniget
import com.insanusmokrassar.postssystem.ktor.client.unipost
import com.insanusmokrassar.postssystem.utils.repos.StandardWriteKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value.*
import io.ktor.client.*
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer
import kotlinx.serialization.builtins.serializer
class KtorStandartWriteKeyValueRepo<K, V> (
private var baseUrl: String,
private var client: HttpClient = HttpClient(),
private var keySerializer: KSerializer<K>,
private var valueSerializer: KSerializer<V>,
) : StandardWriteKeyValueRepo<K, V> {
override val onNewValue: Flow<Pair<K, V>> = client.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
deserializer = PairSerializer(keySerializer, valueSerializer)
)
override val onValueRemoved: Flow<K> = client.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
deserializer = keySerializer
)
override suspend fun set(k: K, v: V) = client.unipost(
buildStandardUrl(
baseUrl,
setRoute
),
BodyPair(KeyValuePostObject.serializer(keySerializer, valueSerializer), KeyValuePostObject(k, v)),
Unit.serializer()
)
override suspend fun unset(k: K) = client.unipost(
buildStandardUrl(
baseUrl,
unsetRoute,
),
BodyPair(keySerializer, k),
Unit.serializer()
)
}

View File

@ -0,0 +1,4 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value
const val keyParameterName = "key"
const val reversedParameterName = "reversed"

View File

@ -0,0 +1,9 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value
import kotlinx.serialization.Serializable
@Serializable
data class KeyValuePostObject<K, V> (
val key: K,
val value: V,
)

View File

@ -0,0 +1,12 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value
const val getRoute = "get"
const val valuesRoute = "values"
const val keysRoute = "keys"
const val containsRoute = "contains"
const val countRoute = "count"
const val onNewValueRoute = "onNewValue"
const val onValueRemovedRoute = "onValueRemoved"
const val setRoute = "set"
const val unsetRoute = "unset"

View File

@ -0,0 +1,27 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.server.key_value
import com.insanusmokrassar.postssystem.utils.repos.StandardKeyValueRepo
import io.ktor.routing.*
import kotlinx.serialization.KSerializer
fun <K, V> Route.configureStandartKeyValueRepoRoutes(
baseSubpart: String,
originalRepo: StandardKeyValueRepo<K, V>,
keySerializer: KSerializer<K>,
valueSerializer: KSerializer<V>,
valueNullableSerializer: KSerializer<V?>,
) {
route(baseSubpart) {
configureReadStandartKeyValueRepoRoutes(
originalRepo,
keySerializer,
valueSerializer,
valueNullableSerializer,
)
configureWriteStandartKeyValueRepoRoutes(
originalRepo,
keySerializer,
valueSerializer,
)
}
}

View File

@ -0,0 +1,76 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.server.key_value
import com.insanusmokrassar.postssystem.ktor.server.extractPagination
import com.insanusmokrassar.postssystem.ktor.server.unianswer
import com.insanusmokrassar.postssystem.ktor.server.uniloadFromQueryOrSendError
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value.*
import io.ktor.application.*
import io.ktor.routing.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
fun <K, V> Route.configureReadStandartKeyValueRepoRoutes (
originalRepo: StandardReadKeyValueRepo<K, V>,
keySerializer: KSerializer<K>,
valueSerializer: KSerializer<V>,
valueNullableSerializer: KSerializer<V?>,
) {
get(getRoute) {
val key = call.uniloadFromQueryOrSendError(
keyParameterName,
keySerializer
) ?: return@get
call.unianswer(
valueNullableSerializer,
originalRepo.get(key)
)
}
get(valuesRoute) {
val parination = call.request.queryParameters.extractPagination;
val reversed = call.uniloadFromQueryOrSendError(
reversedParameterName,
Boolean.serializer()
) ?: return@get
call.unianswer(
PaginationResult.serializer(valueSerializer),
originalRepo.values(parination, reversed)
)
}
get(keysRoute) {
val parination = call.request.queryParameters.extractPagination;
val reversed = call.uniloadFromQueryOrSendError(
reversedParameterName,
Boolean.serializer()
) ?: return@get
call.unianswer(
PaginationResult.serializer(keySerializer),
originalRepo.keys(parination, reversed)
)
}
get(containsRoute) {
val key = call.uniloadFromQueryOrSendError(
keyParameterName,
keySerializer
) ?: return@get
call.unianswer(
Boolean.serializer(),
originalRepo.contains(key)
)
}
get(countRoute) {
call.unianswer(
Long.serializer(),
originalRepo.count()
)
}
}

View File

@ -0,0 +1,44 @@
package com.insanusmokrassar.postssystem.utils.repos.ktor.server.key_value
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
import com.insanusmokrassar.postssystem.ktor.server.uniload
import com.insanusmokrassar.postssystem.utils.repos.StandardWriteKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.key_value.*
import io.ktor.application.*
import io.ktor.routing.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.PairSerializer
fun <K, V> Route.configureWriteStandartKeyValueRepoRoutes (
originalRepo: StandardWriteKeyValueRepo<K, V>,
keySerializer: KSerializer<K>,
valueSerializer: KSerializer<V>,
) {
includeWebsocketHandling(
onNewValueRoute,
originalRepo.onNewValue,
PairSerializer(keySerializer, valueSerializer)
)
includeWebsocketHandling(
onValueRemovedRoute,
originalRepo.onValueRemoved,
keySerializer
)
post(setRoute) {
val (key, value) = call.uniload(
KeyValuePostObject.serializer(keySerializer, valueSerializer)
)
originalRepo.set(key, value)
}
post(unsetRoute) {
val key = call.uniload(
keySerializer
)
originalRepo.unset(key)
}
}