add server realization of post repos

This commit is contained in:
2020-08-14 12:06:37 +06:00
parent 27c06d7d9a
commit 93bd094823
11 changed files with 187 additions and 16 deletions
core
api
src
commonMain
kotlin
com
insanusmokrassar
postssystem
core
exposed
src
main
kotlin
com
insanusmokrassar
postssystem
ktor
client
src
commonMain
kotlin
com
insanusmokrassar
common
src
commonMain
kotlin
com
insanusmokrassar
postssystem
server
ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/ktor/server

@ -21,5 +21,5 @@ interface ReadContentRepo {
/** /**
* @return all [RegisteredContent] by pages basing on their creation date * @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>
} }

@ -131,7 +131,7 @@ private class ContentRepoDatabaseTable(
select { idColumn.eq(id) }.limit(1).firstOrNull() ?.asRegisteredContent(content) 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( return transaction(
db = database db = database
) { ) {

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

@ -27,7 +27,7 @@ class ReadContentRepoKtorClient(
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it) 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( "$baseUrl/$getContentByPaginationRoute".includeQueryParams(
pagination.asUrlQueryParts pagination.asUrlQueryParts
) )

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

@ -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)
}
}

@ -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)
}
}

@ -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)
}
}

@ -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
)

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

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