add server realization of post repos

This commit is contained in:
InsanusMokrassar 2020-08-14 12:06:37 +06:00
parent 27c06d7d9a
commit 93bd094823
11 changed files with 187 additions and 16 deletions

View File

@ -21,5 +21,5 @@ interface ReadContentRepo {
/**
* @return all [RegisteredContent] by pages basing on their creation date
*/
suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent>
suspend fun getContentByPagination(pagination: Pagination): PaginationResult<RegisteredContent>
}

View File

@ -131,7 +131,7 @@ private class ContentRepoDatabaseTable(
select { idColumn.eq(id) }.limit(1).firstOrNull() ?.asRegisteredContent(content)
}
}
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent> {
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<RegisteredContent> {
return transaction(
db = database
) {

View File

@ -1,18 +1,27 @@
package com.insanusmokrassar.postssystem.core.ktor.client.content
import com.insanusmokrassar.postssystem.core.content.api.*
import com.insanusmokrassar.postssystem.core.ktor.contentRootRoute
import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets
class ContentRepoKtorClient(
baseUrl: String,
client: HttpClient = HttpClient {
install(WebSockets)
}
) : ContentRepo, ReadContentRepo by ReadContentRepoKtorClient(
baseUrl,
client
), WriteContentRepo by WriteContentRepoKtorClient(
baseUrl,
client
)
class ContentRepoKtorClient private constructor(
readContentRepo: ReadContentRepo,
writeContentRepo: WriteContentRepo
) : ContentRepo, ReadContentRepo by readContentRepo, WriteContentRepo by writeContentRepo {
constructor(
baseUrl: String,
client: HttpClient = HttpClient {
install(WebSockets)
}
) : this(
ReadContentRepoKtorClient(
"$baseUrl/$contentRootRoute",
client
),
WriteContentRepoKtorClient(
"$baseUrl/$contentRootRoute",
client
)
)
}

View File

@ -27,7 +27,7 @@ class ReadContentRepoKtorClient(
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it)
}
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent> = client.get<ByteArray>(
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<RegisteredContent> = client.get<ByteArray>(
"$baseUrl/$getContentByPaginationRoute".includeQueryParams(
pagination.asUrlQueryParts
)

View File

@ -1,5 +1,7 @@
package com.insanusmokrassar.postssystem.core.ktor
const val contentRootRoute = "content"
const val getContentsIdsRoute = "getContentsIds"
const val getContentByIdRoute = "getContentById"
const val getContentByPaginationRoute = "getContentByPagination"

View File

@ -0,0 +1,26 @@
package com.insanusmokrassar.postssystem.core.ktor.server.content
import com.insanusmokrassar.postssystem.core.content.api.ContentRepo
import com.insanusmokrassar.postssystem.core.ktor.contentRootRoute
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import io.ktor.routing.Route
import io.ktor.routing.route
fun Route.configureContentRepoRoutes(
proxyTo: ContentRepo
) {
route(
contentRootRoute
) {
configureReadContentRepoRoutes(proxyTo)
configureWriteContentRepoRoutes(proxyTo)
}
}
class ContentRepoRoutingConfigurator(
private val proxyTo: ContentRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configureContentRepoRoutes(proxyTo)
}
}

View File

@ -0,0 +1,55 @@
package com.insanusmokrassar.postssystem.core.ktor.server.content
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo
import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import com.insanusmokrassar.postssystem.ktor.server.extractPagination
import com.insanusmokrassar.postssystem.ktor.server.standardKtorSerialFormatContentType
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondBytes
import io.ktor.routing.*
import kotlinx.serialization.builtins.nullable
fun Route.configureReadContentRepoRoutes(
proxyTo: ReadContentRepo
) {
get(getContentsIdsRoute) {
call.respondBytes(
standardKtorSerialFormat.dump(contentIdsSerializer, proxyTo.getContentsIds()),
standardKtorSerialFormatContentType
)
}
get("$getContentByIdRoute/{id}") {
val id = call.parameters["id"].also {
if (it == null) call.respond(HttpStatusCode.BadRequest, "Request must contains id in route")
} ?: return@get
call.respondBytes(
standardKtorSerialFormat.dump(
RegisteredContent.serializer().nullable,
proxyTo.getContentById(id)
),
standardKtorSerialFormatContentType
)
}
get(getContentByPaginationRoute) {
val pagination = call.request.queryParameters.extractPagination
call.respondBytes(
standardKtorSerialFormat.dump(
registeredContentPaginationResultSerializer,
proxyTo.getContentByPagination(pagination)
)
)
}
}
class ReadContentRepoRoutingConfigurator(
private val proxyTo: ReadContentRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configureReadContentRepoRoutes(proxyTo)
}
}

View File

@ -0,0 +1,63 @@
package com.insanusmokrassar.postssystem.core.ktor.server.content
import com.insanusmokrassar.postssystem.core.content.*
import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo
import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
import com.insanusmokrassar.postssystem.ktor.server.standardKtorSerialFormatContentType
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.application.call
import io.ktor.response.respondBytes
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.util.toByteArray
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
fun Route.configureWriteContentRepoRoutes(
proxyTo: WriteContentRepo
) {
includeWebsocketHandling(contentCreatedFlowRoute, proxyTo.contentCreatedFlow) {
standardKtorSerialFormat.dump(RegisteredContent.serializer(), it)
}
includeWebsocketHandling(contentDeletedFlowRoute, proxyTo.contentDeletedFlow) {
standardKtorSerialFormat.dump(RegisteredContent.serializer(), it)
}
post(registerContentRoute) {
val content = standardKtorSerialFormat.load(
Content.serializer(),
call.request.receiveChannel().toByteArray()
)
val registered = proxyTo.registerContent(content)
call.respondBytes(
standardKtorSerialFormat.dump(
RegisteredContent.serializer().nullable,
registered
),
standardKtorSerialFormatContentType
)
}
post(deleteContentRoute) {
val contentId = standardKtorSerialFormat.load(
ContentId.serializer(),
call.request.receiveChannel().toByteArray()
)
val isDeleted = proxyTo.deleteContent(contentId)
call.respondBytes(
standardKtorSerialFormat.dump(
Boolean.serializer(),
isDeleted
),
standardKtorSerialFormatContentType
)
}
}
class WriteContentRepoRoutingConfigurator(
private val proxyTo: WriteContentRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configureWriteContentRepoRoutes(proxyTo)
}
}

View File

@ -0,0 +1,10 @@
package com.insanusmokrassar.postssystem.ktor.server
import com.insanusmokrassar.postssystem.utils.common.pagination.*
import io.ktor.http.Parameters
val Parameters.extractPagination: Pagination
get() = SimplePagination(
get("page") ?.toIntOrNull() ?: 0,
get("size") ?.toIntOrNull() ?: defaultMediumPageSize
)

View File

@ -1,6 +1,7 @@
package com.insanusmokrassar.postssystem.ktor.server.configurators
import io.ktor.application.*
import io.ktor.routing.Route
import io.ktor.routing.Routing
import kotlinx.serialization.ContextualSerialization
import kotlinx.serialization.Serializable
@ -9,7 +10,7 @@ import kotlinx.serialization.Serializable
class ApplicationRoutingConfigurator(
private val elements: List<@ContextualSerialization Element>
) : KtorApplicationConfigurator {
interface Element { operator fun Routing.invoke() }
interface Element { operator fun Route.invoke() }
override fun Application.configure() {
try {

View File

@ -0,0 +1,5 @@
package com.insanusmokrassar.postssystem.ktor.server
import io.ktor.http.ContentType
val standardKtorSerialFormatContentType = ContentType.Application.Cbor