Merge branch 'master' into posting-ktor-common

This commit is contained in:
000Sanya
2020-08-14 22:12:16 +10:00
21 changed files with 498 additions and 92 deletions
core
api
src
commonMain
kotlin
com
insanusmokrassar
postssystem
core
exposed
src
main
kotlin
com
insanusmokrassar
postssystem
ktor
ktor
client
src
commonMain
kotlin
com
insanusmokrassar
postssystem
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(
readContentRepo: ReadContentRepo,
writeContentRepo: WriteContentRepo
) : ContentRepo, ReadContentRepo by readContentRepo, WriteContentRepo by writeContentRepo {
constructor(
baseUrl: String, baseUrl: String,
client: HttpClient = HttpClient { client: HttpClient = HttpClient {
install(WebSockets) install(WebSockets)
} }
) : ContentRepo, ReadContentRepo by ReadContentRepoKtorClient( ) : this(
baseUrl, ReadContentRepoKtorClient(
"$baseUrl/$contentRootRoute",
client client
), WriteContentRepo by WriteContentRepoKtorClient( ),
baseUrl, WriteContentRepoKtorClient(
"$baseUrl/$contentRootRoute",
client client
) )
)
}

@ -5,6 +5,7 @@ import com.insanusmokrassar.postssystem.core.content.RegisteredContent
import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo
import com.insanusmokrassar.postssystem.core.ktor.* import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.ktor.* import com.insanusmokrassar.postssystem.ktor.*
import com.insanusmokrassar.postssystem.ktor.client.uniget
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
@ -21,17 +22,13 @@ class ReadContentRepoKtorClient(
standardKtorSerialFormat.load(contentIdsSerializer, it) standardKtorSerialFormat.load(contentIdsSerializer, it)
} }
override suspend fun getContentById(id: ContentId): RegisteredContent? = client.get<ByteArray>( override suspend fun getContentById(id: ContentId): RegisteredContent? = client.uniget(
"$baseUrl/$getContentByIdRoute/$id" "$baseUrl/$getContentByIdRoute/$id",
).let { RegisteredContent.serializer().nullable
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it) )
}
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<RegisteredContent> = client.uniget(
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent> = client.get<ByteArray>( "$baseUrl/$getContentByPaginationRoute".includeQueryParams(pagination.asUrlQueryParts),
"$baseUrl/$getContentByPaginationRoute".includeQueryParams( registeredContentPaginationResultSerializer
pagination.asUrlQueryParts
) )
).let {
standardKtorSerialFormat.load(registeredContentPaginationResultSerializer, it)
}
} }

@ -3,7 +3,7 @@ package com.insanusmokrassar.postssystem.core.ktor.client.content
import com.insanusmokrassar.postssystem.core.content.* import com.insanusmokrassar.postssystem.core.content.*
import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo
import com.insanusmokrassar.postssystem.core.ktor.* import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow import com.insanusmokrassar.postssystem.ktor.client.*
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.post import io.ktor.client.request.post
@ -28,17 +28,15 @@ class WriteContentRepoKtorClient(
standardKtorSerialFormat.load(RegisteredContent.serializer(), it) standardKtorSerialFormat.load(RegisteredContent.serializer(), it)
} }
override suspend fun registerContent(content: Content): RegisteredContent? = client.post<ByteArray> { override suspend fun registerContent(content: Content): RegisteredContent? = client.unipost(
url("$baseUrl/$registerContentRoute") "$baseUrl/$registerContentRoute",
body = standardKtorSerialFormat.dump(Content.serializer(), content) BodyPair(Content.serializer(), content),
}.let { RegisteredContent.serializer().nullable
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it) )
}
override suspend fun deleteContent(id: ContentId): Boolean = client.post<ByteArray> { override suspend fun deleteContent(id: ContentId): Boolean = client.unipost(
url("$baseUrl/$deleteContentRoute") "$baseUrl/$deleteContentRoute",
body = standardKtorSerialFormat.dump(ContentId.serializer(), id) BodyPair(ContentId.serializer(), id),
}.let { Boolean.serializer()
standardKtorSerialFormat.load(Boolean.serializer(), it) )
}
} }

@ -1,18 +1,27 @@
package com.insanusmokrassar.postssystem.core.ktor.client.post package com.insanusmokrassar.postssystem.core.ktor.client.post
import com.insanusmokrassar.postssystem.core.ktor.postsRootRoute
import com.insanusmokrassar.postssystem.core.post.repo.* import com.insanusmokrassar.postssystem.core.post.repo.*
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 PostsRepoKtorClient( class PostsRepoKtorClient private constructor(
readPostsRepo: ReadPostsRepo,
writePostsRepo: WritePostsRepo
) : PostsRepo, ReadPostsRepo by readPostsRepo, WritePostsRepo by writePostsRepo {
constructor(
baseUrl: String, baseUrl: String,
client: HttpClient = HttpClient { client: HttpClient = HttpClient {
install(WebSockets) install(WebSockets)
} }
) : PostsRepo, ReadPostsRepo by ReadPostsRepoKtorClient( ) : this(
baseUrl, ReadPostsRepoKtorClient(
"${baseUrl}/$postsRootRoute",
client client
), WritePostsRepo by WritePostsRepoKtorClient( ),
baseUrl, WritePostsRepoKtorClient(
"${baseUrl}/$postsRootRoute",
client client
) )
)
}

@ -6,6 +6,7 @@ import com.insanusmokrassar.postssystem.core.post.PostId
import com.insanusmokrassar.postssystem.core.post.RegisteredPost import com.insanusmokrassar.postssystem.core.post.RegisteredPost
import com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo import com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo
import com.insanusmokrassar.postssystem.ktor.* import com.insanusmokrassar.postssystem.ktor.*
import com.insanusmokrassar.postssystem.ktor.client.uniget
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
@ -23,35 +24,31 @@ class ReadPostsRepoKtorClient(
standardKtorSerialFormat.load(postIdsSerializer, it) standardKtorSerialFormat.load(postIdsSerializer, it)
} }
override suspend fun getPostById(id: PostId): RegisteredPost? = client.get<ByteArray>( override suspend fun getPostById(id: PostId): RegisteredPost? = client.uniget(
"$baseUrl/$getPostByIdRoute/$id" "$baseUrl/$getPostByIdRoute/$id",
).let { RegisteredPost.serializer().nullable
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it) )
}
override suspend fun getPostsByContent(id: ContentId): List<RegisteredPost> = client.get<ByteArray>( override suspend fun getPostsByContent(id: ContentId): List<RegisteredPost> = client.uniget(
"$baseUrl/$getPostsByContentRoute/$id" "$baseUrl/$getPostsByContentRoute/$id",
).let { registeredPostsListSerializer
standardKtorSerialFormat.load(registeredPostsListSerializer, it) )
}
override suspend fun getPostsByCreatingDates( override suspend fun getPostsByCreatingDates(
from: DateTime, from: DateTime,
to: DateTime, to: DateTime,
pagination: Pagination pagination: Pagination
): PaginationResult<RegisteredPost> = client.get<ByteArray>( ): PaginationResult<RegisteredPost> = client.uniget(
"$baseUrl/$getPostsByCreatingDatesRoute".includeQueryParams( "$baseUrl/$getPostsByCreatingDatesRoute".includeQueryParams(
(from to to).asFromToUrlPart + pagination.asUrlQueryParts (from to to).asFromToUrlPart + pagination.asUrlQueryParts
),
registeredPostsPaginationResultSerializer
) )
).let {
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
}
override suspend fun getPostsByPagination(pagination: Pagination): PaginationResult<RegisteredPost> = client.get<ByteArray>( override suspend fun getPostsByPagination(pagination: Pagination): PaginationResult<RegisteredPost> = client.uniget(
"$baseUrl/$getPostsByPaginationRoute".includeQueryParams( "$baseUrl/$getPostsByPaginationRoute".includeQueryParams(
pagination.asUrlQueryParts pagination.asUrlQueryParts
),
registeredPostsPaginationResultSerializer
) )
).let {
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
}
} }

@ -3,7 +3,7 @@ package com.insanusmokrassar.postssystem.core.ktor.client.post
import com.insanusmokrassar.postssystem.core.ktor.* import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.core.post.* import com.insanusmokrassar.postssystem.core.post.*
import com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo import com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow import com.insanusmokrassar.postssystem.ktor.client.*
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets import io.ktor.client.features.websocket.WebSockets
@ -35,25 +35,21 @@ class WritePostsRepoKtorClient (
standardKtorSerialFormat.load(RegisteredPost.serializer(), it) standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
} }
override suspend fun createPost(post: Post): RegisteredPost? = client.post<ByteArray> { override suspend fun createPost(post: Post): RegisteredPost? = client.unipost(
url("$baseUrl/$createPostRoute") "$baseUrl/$createPostRoute",
body = standardKtorSerialFormat.dump(Post.serializer(), post) BodyPair(Post.serializer(), post),
}.let { RegisteredPost.serializer().nullable
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it) )
}
override suspend fun deletePost(id: PostId): Boolean = client.post<ByteArray> { override suspend fun deletePost(id: PostId): Boolean = client.unipost(
url("$baseUrl/$createPostRoute") "$baseUrl/$deletePostRoute",
body = standardKtorSerialFormat.dump(PostId.serializer(), id) BodyPair(PostId.serializer(), id),
}.let { Boolean.serializer()
standardKtorSerialFormat.load(Boolean.serializer(), it) )
}
override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.post<ByteArray> {
url("$baseUrl/$createPostRoute")
body = standardKtorSerialFormat.dump(UpdatePostObject.serializer(), UpdatePostObject(postId, post))
}.let {
standardKtorSerialFormat.load(Boolean.serializer(), it)
}
override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.unipost(
"$baseUrl/$updatePostContentRoute",
BodyPair(UpdatePostObject.serializer(), UpdatePostObject(postId, post)),
Boolean.serializer()
)
} }

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

@ -1,5 +1,7 @@
package com.insanusmokrassar.postssystem.core.ktor package com.insanusmokrassar.postssystem.core.ktor
const val postsRootRoute = "post"
const val getPostsIdsRoute = "getPostsIds" const val getPostsIdsRoute = "getPostsIds"
const val getPostByIdRoute = "getPostById" const val getPostByIdRoute = "getPostById"
const val getPostsByContentRoute = "getPostsByContent" const val getPostsByContentRoute = "getPostsByContent"

@ -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,56 @@
package com.insanusmokrassar.postssystem.core.ktor.server.content
import com.insanusmokrassar.postssystem.core.content.ContentId
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: ContentId = 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,24 @@
package com.insanusmokrassar.postssystem.core.ktor.server.post
import com.insanusmokrassar.postssystem.core.ktor.postsRootRoute
import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import io.ktor.routing.Route
import io.ktor.routing.route
fun Route.configurePostsRepoRoutes(
proxyTo: PostsRepo
) {
route(postsRootRoute) {
configureReadPostsRepoRoutes(proxyTo)
configureWritePostsRepoRoutes(proxyTo)
}
}
class PostsRepoRoutingConfigurator(
private val proxyTo: PostsRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configurePostsRepoRoutes(proxyTo)
}
}

@ -0,0 +1,93 @@
package com.insanusmokrassar.postssystem.core.ktor.server.post
import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.core.post.PostId
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
import com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo
import com.insanusmokrassar.postssystem.ktor.server.*
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import com.insanusmokrassar.postssystem.utils.common.MAX_DATE
import com.insanusmokrassar.postssystem.utils.common.MIN_DATE
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondBytes
import io.ktor.routing.Route
import io.ktor.routing.get
import kotlinx.serialization.builtins.nullable
fun Route.configureReadPostsRepoRoutes(
proxyTo: ReadPostsRepo
) {
get(getPostsIdsRoute) {
call.respondBytes(
standardKtorSerialFormat.dump(postIdsSerializer, proxyTo.getPostsIds()),
standardKtorSerialFormatContentType
)
}
get("$getPostByIdRoute/{id}") {
val id: PostId = call.parameters["id"].also {
if (it == null) {
call.respond(HttpStatusCode.BadRequest, "request must contains id")
}
} ?: return@get
call.respondBytes(
standardKtorSerialFormat.dump(
RegisteredPost.serializer().nullable,
proxyTo.getPostById(id)
),
standardKtorSerialFormatContentType
)
}
get("$getPostsByContentRoute/{id}") {
val id: ContentId = call.parameters["id"].also {
if (it == null) {
call.respond(HttpStatusCode.BadRequest, "request must contains id")
}
} ?: return@get
call.respondBytes(
standardKtorSerialFormat.dump(
registeredPostsListSerializer,
proxyTo.getPostsByContent(id)
),
standardKtorSerialFormatContentType
)
}
get(getPostsByCreatingDatesRoute) {
val fromToDateTime = call.request.queryParameters.extractFromToDateTime
val pagination = call.request.queryParameters.extractPagination
call.respondBytes(
standardKtorSerialFormat.dump(
registeredPostsPaginationResultSerializer,
proxyTo.getPostsByCreatingDates(
fromToDateTime.first ?: MIN_DATE,
fromToDateTime.second ?: MAX_DATE,
pagination
)
),
standardKtorSerialFormatContentType
)
}
get(getPostsByPaginationRoute) {
val pagination = call.request.queryParameters.extractPagination
call.respondBytes(
standardKtorSerialFormat.dump(
registeredPostsPaginationResultSerializer,
proxyTo.getPostsByPagination(pagination)
),
standardKtorSerialFormatContentType
)
}
}
class ReadPostsRepoRoutingConfigurator(
private val proxyTo: ReadPostsRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configureReadPostsRepoRoutes(proxyTo)
}
}

@ -0,0 +1,79 @@
package com.insanusmokrassar.postssystem.core.ktor.server.post
import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.core.post.*
import com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo
import com.insanusmokrassar.postssystem.ktor.server.configurators.ApplicationRoutingConfigurator
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.application.call
import io.ktor.response.respondBytes
import io.ktor.routing.*
import io.ktor.util.toByteArray
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
fun Route.configureWritePostsRepoRoutes(
proxyTo: WritePostsRepo
) {
includeWebsocketHandling(postCreatedFlowRoute, proxyTo.postCreatedFlow) {
standardKtorSerialFormat.dump(RegisteredPost.serializer(), it)
}
includeWebsocketHandling(postDeletedFlowRoute, proxyTo.postDeletedFlow) {
standardKtorSerialFormat.dump(RegisteredPost.serializer(), it)
}
includeWebsocketHandling(postUpdatedFlowRoute, proxyTo.postUpdatedFlow) {
standardKtorSerialFormat.dump(RegisteredPost.serializer(), it)
}
post(createPostRoute) {
val post = standardKtorSerialFormat.load(
Post.serializer(),
call.request.receiveChannel().toByteArray()
)
call.respondBytes(
standardKtorSerialFormat.dump(
RegisteredPost.serializer().nullable,
proxyTo.createPost(post)
)
)
}
post(deletePostRoute) {
val postId = standardKtorSerialFormat.load(
PostId.serializer(),
call.request.receiveChannel().toByteArray()
)
call.respondBytes(
standardKtorSerialFormat.dump(
Boolean.serializer(),
proxyTo.deletePost(postId)
)
)
}
post(updatePostContentRoute) {
val updatePostObject = standardKtorSerialFormat.load(
UpdatePostObject.serializer(),
call.request.receiveChannel().toByteArray()
)
call.respondBytes(
standardKtorSerialFormat.dump(
Boolean.serializer(),
proxyTo.updatePostContent(updatePostObject.postId, updatePostObject.post)
)
)
}
}
class WritePostsRepoRoutingConfigurator(
private val proxyTo: WritePostsRepo
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
configureWritePostsRepoRoutes(proxyTo)
}
}

@ -0,0 +1,28 @@
package com.insanusmokrassar.postssystem.ktor.client
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.request.post
import kotlinx.serialization.*
typealias BodyPair<T> = Pair<SerializationStrategy<T>, T>
suspend fun <ResultType> HttpClient.uniget(
url: String,
resultDeserializer: DeserializationStrategy<ResultType>
) = get<ByteArray>(
url
).let {
standardKtorSerialFormat.load(resultDeserializer, it)
}
suspend fun <BodyType, ResultType> HttpClient.unipost(
url: String,
bodyInfo: BodyPair<BodyType>,
resultDeserializer: DeserializationStrategy<ResultType>
) = post<ByteArray>(url) {
body = standardKtorSerialFormat.dump(bodyInfo.first, bodyInfo.second)
}.let {
standardKtorSerialFormat.load(resultDeserializer, it)
}

@ -0,0 +1,11 @@
package com.insanusmokrassar.postssystem.ktor.server
import com.insanusmokrassar.postssystem.ktor.FromToDateTime
import com.soywiz.klock.DateTime
import io.ktor.http.Parameters
val Parameters.extractFromToDateTime: FromToDateTime
get() = FromToDateTime(
get("from") ?.toDoubleOrNull() ?.let { DateTime(it) },
get("to") ?.toDoubleOrNull() ?.let { DateTime(it) }
)

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