add all client realizations for core repos

This commit is contained in:
InsanusMokrassar 2020-08-11 22:15:07 +06:00
parent 336e169147
commit 3d3d184636
35 changed files with 347 additions and 99 deletions

View File

@ -1,9 +1,3 @@
package com.insanusmokrassar.postssystem.core.content.api package com.insanusmokrassar.postssystem.core.content.api
import com.insanusmokrassar.postssystem.core.content.RegisteredContent interface ContentRepo : ReadContentRepo, WriteContentRepo
import kotlinx.coroutines.flow.Flow
interface ContentRepo : ReadContentRepo, WriteContentRepo {
val contentCreatedFlow: Flow<RegisteredContent>
val contentDeletedFlow: Flow<RegisteredContent>
}

View File

@ -2,8 +2,8 @@ package com.insanusmokrassar.postssystem.core.content.api
import com.insanusmokrassar.postssystem.core.content.ContentId import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.core.content.RegisteredContent import com.insanusmokrassar.postssystem.core.content.RegisteredContent
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
/** /**
* Simple read API by different properties of [com.insanusmokrassar.postssystem.core.content.Content]. * Simple read API by different properties of [com.insanusmokrassar.postssystem.core.content.Content].

View File

@ -1,8 +1,12 @@
package com.insanusmokrassar.postssystem.core.content.api package com.insanusmokrassar.postssystem.core.content.api
import com.insanusmokrassar.postssystem.core.content.* import com.insanusmokrassar.postssystem.core.content.*
import kotlinx.coroutines.flow.Flow
interface WriteContentRepo { interface WriteContentRepo {
val contentCreatedFlow: Flow<RegisteredContent>
val contentDeletedFlow: Flow<RegisteredContent>
suspend fun registerContent(content: Content): RegisteredContent? suspend fun registerContent(content: Content): RegisteredContent?
suspend fun deleteContent(id: ContentId): Boolean suspend fun deleteContent(id: ContentId): Boolean
} }

View File

@ -1,7 +1,10 @@
package com.insanusmokrassar.postssystem.core.post package com.insanusmokrassar.postssystem.core.post
import com.insanusmokrassar.postssystem.core.content.ContentId import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.utils.common.UnixMillis
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
typealias PostId = String typealias PostId = String
typealias ContentIds = List<ContentId> typealias ContentIds = List<ContentId>
@ -9,35 +12,50 @@ typealias ContentIds = List<ContentId>
/** /**
* Base interface for creating of new post. Usually, it is just [SimplePost] instance * Base interface for creating of new post. Usually, it is just [SimplePost] instance
*/ */
interface Post { @Serializable
val content: ContentIds sealed class Post {
abstract val content: ContentIds
} }
/** /**
* Root entity of whole system. Can be retrieved from [com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo] by * Root entity of the whole system. Can be retrieved from [com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo]
* getting and created in [com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo] by inserting of [Post] instance * by getting and created in [com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo] by inserting of [Post]
* instance
*/ */
interface RegisteredPost : Post { @Serializable
val id: PostId sealed class RegisteredPost : Post() {
abstract val id: PostId
override val content: ContentIds abstract override val content: ContentIds
val creationDate: DateTime abstract val creationDate: DateTime
} }
/** /**
* Base and currently (1st Nov 2019) single realisation of [Post]. There is [SimpleRegisteredPost] which is technically * Base and currently (1st Nov 2019) single realisation of [Post]. There is [SimpleRegisteredPost] which is technically
* is [Post] too, but it is not direct [Post] realisation * is [Post] too, but it is not direct [Post] realisation
*/ */
@Serializable
data class SimplePost( data class SimplePost(
override val content: ContentIds override val content: ContentIds
) : Post ) : Post()
/** /**
* Base and currently (1st Nov 2019) single realisation of [RegisteredPost] * Base and currently (1st Nov 2019) single realisation of [RegisteredPost]
*/ */
@Serializable
data class SimpleRegisteredPost( data class SimpleRegisteredPost(
override val id: PostId, override val id: PostId,
override val content: ContentIds, override val content: ContentIds,
override val creationDate: DateTime = DateTime.now() private val creationDateTimeMillis: UnixMillis
) : RegisteredPost ) : RegisteredPost() {
@Transient
override val creationDate: DateTime = DateTime(creationDateTimeMillis)
}
@Suppress("FunctionName")
fun RegisteredPost(
id: PostId,
content: ContentIds,
creationDate: DateTime
) = SimpleRegisteredPost(id, content, creationDate.unixMillis)

View File

@ -5,8 +5,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.utils.common.MAX_DATE import com.insanusmokrassar.postssystem.utils.common.MAX_DATE
import com.insanusmokrassar.postssystem.utils.common.MIN_DATE import com.insanusmokrassar.postssystem.utils.common.MIN_DATE
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
/** /**
@ -31,7 +30,11 @@ interface ReadPostsRepo {
/** /**
* @return all [RegisteredPost]s which was registered between [from] and [to]. Range will be used INCLUSIVE, line \[[from], [to]\] * @return all [RegisteredPost]s which was registered between [from] and [to]. Range will be used INCLUSIVE, line \[[from], [to]\]
*/ */
suspend fun getPostsByCreatingDates(from: DateTime = MIN_DATE, to: DateTime = MAX_DATE): List<RegisteredPost> suspend fun getPostsByCreatingDates(
from: DateTime = MIN_DATE,
to: DateTime = MAX_DATE,
pagination: Pagination = FirstPagePagination()
): PaginationResult<RegisteredPost>
/** /**
* @return all posts by pages basing on their creation date * @return all posts by pages basing on their creation date
@ -41,8 +44,10 @@ interface ReadPostsRepo {
suspend fun ReadPostsRepo.getPostsByCreatingDates( suspend fun ReadPostsRepo.getPostsByCreatingDates(
from: DateTime? = null, from: DateTime? = null,
to: DateTime? = null to: DateTime? = null,
pagination: Pagination = FirstPagePagination()
) = getPostsByCreatingDates( ) = getPostsByCreatingDates(
from ?: MIN_DATE, from ?: MIN_DATE,
to ?: MAX_DATE to ?: MAX_DATE,
pagination
) )

View File

@ -5,7 +5,7 @@ import com.insanusmokrassar.postssystem.core.content.api.ContentRepo
import com.insanusmokrassar.postssystem.core.exposed.content.* import com.insanusmokrassar.postssystem.core.exposed.content.*
import com.insanusmokrassar.postssystem.core.generateContentId import com.insanusmokrassar.postssystem.core.generateContentId
import com.insanusmokrassar.postssystem.exposed.commons.paginate import com.insanusmokrassar.postssystem.exposed.commons.paginate
import com.insanusmokrassar.postssystem.utils.repos.pagination.* import com.insanusmokrassar.postssystem.utils.common.pagination.*
import kotlinx.coroutines.channels.BroadcastChannel import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

View File

@ -5,7 +5,7 @@ import com.insanusmokrassar.postssystem.core.generatePostId
import com.insanusmokrassar.postssystem.core.post.* import com.insanusmokrassar.postssystem.core.post.*
import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo
import com.insanusmokrassar.postssystem.exposed.commons.paginate import com.insanusmokrassar.postssystem.exposed.commons.paginate
import com.insanusmokrassar.postssystem.utils.repos.pagination.* import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.soywiz.klock.* import com.soywiz.klock.*
import kotlinx.coroutines.channels.BroadcastChannel import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
@ -100,7 +100,7 @@ private class PostsRepoDatabaseTable(
SimpleRegisteredPost( SimpleRegisteredPost(
id, id,
contentsTable.getPostContents(id), contentsTable.getPostContents(id),
dateTimeFormat.parse(get(creationDateColumn)).local dateTimeFormat.parse(get(creationDateColumn)).local.unixMillis
) )
} }
@ -176,11 +176,22 @@ private class PostsRepoDatabaseTable(
} }
} }
override suspend fun getPostsByCreatingDates(from: DateTime, to: DateTime): List<RegisteredPost> { override suspend fun getPostsByCreatingDates(
from: DateTime,
to: DateTime,
pagination: Pagination
): PaginationResult<RegisteredPost> {
return transaction( return transaction(
db = database db = database
) { ) {
select { creationDateColumn.between(from, to) }.map { it.toRegisteredPost() } select { creationDateColumn.between(from, to) }.paginate(
pagination
).map {
it.toRegisteredPost()
}.createPaginationResult(
pagination,
selectAll().count()
)
} }
} }

View File

@ -1,38 +1,18 @@
package com.insanusmokrassar.postssystem.core.ktor.client.content package com.insanusmokrassar.postssystem.core.ktor.client.content
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
import com.insanusmokrassar.postssystem.core.content.api.* import com.insanusmokrassar.postssystem.core.content.api.*
import com.insanusmokrassar.postssystem.core.ktor.contentCreatedFlowRoute
import com.insanusmokrassar.postssystem.core.ktor.contentDeletedFlowRoute
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import kotlinx.coroutines.flow.Flow import io.ktor.client.features.websocket.WebSockets
class ContentRepoKtorClient( class ContentRepoKtorClient(
baseUrl: String, baseUrl: String,
client: HttpClient = HttpClient() client: HttpClient = HttpClient {
) : ContentRepo, install(WebSockets)
ReadContentRepo by ReadContentRepoKtorClient( }
) : ContentRepo, ReadContentRepo by ReadContentRepoKtorClient(
baseUrl, baseUrl,
client client
), ), WriteContentRepo by WriteContentRepoKtorClient(
WriteContentRepo by WriteContentRepoKtorClient(
baseUrl, baseUrl,
client client
) { )
override val contentCreatedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
client,
"$baseUrl/$contentCreatedFlowRoute"
) {
standardKtorSerializer.load(RegisteredContent.serializer(), it)
}
override val contentDeletedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
client,
"$baseUrl/$contentDeletedFlowRoute"
) {
standardKtorSerializer.load(RegisteredContent.serializer(), it)
}
}

View File

@ -4,9 +4,9 @@ import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.core.content.RegisteredContent 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.standardKtorSerializer import com.insanusmokrassar.postssystem.ktor.*
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.get import io.ktor.client.request.get
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
@ -18,18 +18,20 @@ class ReadContentRepoKtorClient(
override suspend fun getContentsIds(): Set<ContentId> = client.get<ByteArray>( override suspend fun getContentsIds(): Set<ContentId> = client.get<ByteArray>(
"$baseUrl/$getContentsIdsRoute" "$baseUrl/$getContentsIdsRoute"
).let { ).let {
standardKtorSerializer.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.get<ByteArray>(
"$baseUrl/$getContentByIdRoute" "$baseUrl/$getContentByIdRoute/$id"
).let { ).let {
standardKtorSerializer.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<out RegisteredContent> = client.get<ByteArray>(
"$baseUrl/$getContentByPaginationRoute" "$baseUrl/$getContentByPaginationRoute".includeQueryParams(
pagination.asUrlQueryParts
)
).let { ).let {
standardKtorSerializer.load(registeredContentPaginationResultSerializer, it) standardKtorSerialFormat.load(registeredContentPaginationResultSerializer, it)
} }
} }

View File

@ -2,12 +2,13 @@ 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.deleteContentRoute import com.insanusmokrassar.postssystem.core.ktor.*
import com.insanusmokrassar.postssystem.core.ktor.registerContentRoute import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer 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
import io.ktor.client.request.url import io.ktor.client.request.url
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
@ -15,17 +16,31 @@ class WriteContentRepoKtorClient(
private val baseUrl: String, private val baseUrl: String,
private val client: HttpClient = HttpClient() private val client: HttpClient = HttpClient()
) : WriteContentRepo { ) : WriteContentRepo {
override val contentCreatedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
client,
"$baseUrl/$contentCreatedFlowRoute"
) {
standardKtorSerialFormat.load(RegisteredContent.serializer(), it)
}
override val contentDeletedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
client,
"$baseUrl/$contentDeletedFlowRoute"
) {
standardKtorSerialFormat.load(RegisteredContent.serializer(), it)
}
override suspend fun registerContent(content: Content): RegisteredContent? = client.post<ByteArray> { override suspend fun registerContent(content: Content): RegisteredContent? = client.post<ByteArray> {
url("$baseUrl/$registerContentRoute") url("$baseUrl/$registerContentRoute")
body = standardKtorSerializer.dump(Content.serializer(), content) body = standardKtorSerialFormat.dump(Content.serializer(), content)
}.let { }.let {
standardKtorSerializer.load(RegisteredContent.serializer().nullable, it) standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it)
} }
override suspend fun deleteContent(id: ContentId): Boolean = client.post<ByteArray> { override suspend fun deleteContent(id: ContentId): Boolean = client.post<ByteArray> {
url("$baseUrl/$deleteContentRoute") url("$baseUrl/$deleteContentRoute")
body = standardKtorSerializer.dump(ContentId.serializer(), id) body = standardKtorSerialFormat.dump(ContentId.serializer(), id)
}.let { }.let {
standardKtorSerializer.load(Boolean.serializer(), it) standardKtorSerialFormat.load(Boolean.serializer(), it)
} }
} }

View File

@ -0,0 +1,18 @@
package com.insanusmokrassar.postssystem.core.ktor.client.post
import com.insanusmokrassar.postssystem.core.post.repo.*
import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets
class PostsRepoKtorClient(
baseUrl: String,
client: HttpClient = HttpClient {
install(WebSockets)
}
) : PostsRepo, ReadPostsRepo by ReadPostsRepoKtorClient(
baseUrl,
client
), WritePostsRepo by WritePostsRepoKtorClient(
baseUrl,
client
)

View File

@ -0,0 +1,57 @@
package com.insanusmokrassar.postssystem.core.ktor.client.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.*
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import com.soywiz.klock.DateTime
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import kotlinx.serialization.builtins.nullable
class ReadPostsRepoKtorClient(
private val baseUrl: String,
private val client: HttpClient = HttpClient()
) : ReadPostsRepo {
override suspend fun getPostsIds(): Set<PostId> = client.get<ByteArray>(
"$baseUrl/$getPostsIdsRoute"
).let {
standardKtorSerialFormat.load(postIdsSerializer, it)
}
override suspend fun getPostById(id: PostId): RegisteredPost? = client.get<ByteArray>(
"$baseUrl/$getPostByIdRoute/$id"
).let {
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it)
}
override suspend fun getPostsByContent(id: ContentId): List<RegisteredPost> = client.get<ByteArray>(
"$baseUrl/$getPostsByContentRoute/$id"
).let {
standardKtorSerialFormat.load(registeredPostsListSerializer, it)
}
override suspend fun getPostsByCreatingDates(
from: DateTime,
to: DateTime,
pagination: Pagination
): PaginationResult<RegisteredPost> = client.get<ByteArray>(
"$baseUrl/$getPostsByCreatingDatesRoute".includeQueryParams(
(from to to).asFromToUrlPart + pagination.asUrlQueryParts
)
).let {
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
}
override suspend fun getPostsByPagination(pagination: Pagination): PaginationResult<RegisteredPost> = client.get<ByteArray>(
"$baseUrl/$getPostsByPaginationRoute".includeQueryParams(
pagination.asUrlQueryParts
)
).let {
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
}
}

View File

@ -0,0 +1,59 @@
package com.insanusmokrassar.postssystem.core.ktor.client.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.client.createStandardWebsocketFlow
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets
import io.ktor.client.request.post
import io.ktor.client.request.url
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
class WritePostsRepoKtorClient (
private val baseUrl: String,
private val client: HttpClient = HttpClient {
install(WebSockets)
}
) : WritePostsRepo {
override val postCreatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
"$baseUrl/$postCreatedFlowRoute"
) {
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
}
override val postDeletedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
"$baseUrl/$postDeletedFlowRoute"
) {
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
}
override val postUpdatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
"$baseUrl/$postUpdatedFlowRoute"
) {
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
}
override suspend fun createPost(post: Post): RegisteredPost? = client.post<ByteArray> {
url("$baseUrl/$createPostRoute")
body = standardKtorSerialFormat.dump(Post.serializer(), post)
}.let {
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it)
}
override suspend fun deletePost(id: PostId): Boolean = client.post<ByteArray> {
url("$baseUrl/$createPostRoute")
body = standardKtorSerialFormat.dump(PostId.serializer(), id)
}.let {
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)
}
}

View File

@ -0,0 +1,14 @@
package com.insanusmokrassar.postssystem.core.ktor
const val getPostsIdsRoute = "getPostsIds"
const val getPostByIdRoute = "getPostById"
const val getPostsByContentRoute = "getPostsByContent"
const val getPostsByCreatingDatesRoute = "getPostsByCreatingDates"
const val getPostsByPaginationRoute = "getPostsByPagination"
const val postCreatedFlowRoute = "postCreatedFlow"
const val postDeletedFlowRoute = "postDeletedFlow"
const val postUpdatedFlowRoute = "postUpdatedFlow"
const val createPostRoute = "createPost"
const val deletePostRoute = "deletePost"
const val updatePostContentRoute = "updatePostContent"

View File

@ -1,8 +1,13 @@
package com.insanusmokrassar.postssystem.core.ktor package com.insanusmokrassar.postssystem.core.ktor
import com.insanusmokrassar.postssystem.core.content.RegisteredContent import com.insanusmokrassar.postssystem.core.content.RegisteredContent
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
import com.insanusmokrassar.postssystem.ktor.setIdsSerializer import com.insanusmokrassar.postssystem.ktor.setIdsSerializer
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import kotlinx.serialization.builtins.ListSerializer
val contentIdsSerializer = setIdsSerializer val contentIdsSerializer = setIdsSerializer
val postIdsSerializer = setIdsSerializer
val registeredPostsListSerializer = ListSerializer(RegisteredPost.serializer())
val registeredPostsPaginationResultSerializer = PaginationResult.serializer(RegisteredPost.serializer())
val registeredContentPaginationResultSerializer = PaginationResult.serializer(RegisteredContent.serializer()) val registeredContentPaginationResultSerializer = PaginationResult.serializer(RegisteredContent.serializer())

View File

@ -0,0 +1,11 @@
package com.insanusmokrassar.postssystem.core.ktor
import com.insanusmokrassar.postssystem.core.post.Post
import com.insanusmokrassar.postssystem.core.post.PostId
import kotlinx.serialization.Serializable
@Serializable
data class UpdatePostObject(
val postId: PostId,
val post: Post
)

View File

@ -1,6 +1,6 @@
package com.insanusmokrassar.postssystem.exposed.commons package com.insanusmokrassar.postssystem.exposed.commons
import com.insanusmokrassar.postssystem.utils.repos.pagination.* import com.insanusmokrassar.postssystem.utils.common.pagination.*
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
fun Query.paginate(with: Pagination, orderBy: Pair<Expression<*>, SortOrder>? = null) = limit( fun Query.paginate(with: Pagination, orderBy: Pair<Expression<*>, SortOrder>? = null) = limit(

View File

@ -62,3 +62,8 @@ inline fun <reified T> createStandardWebsocketFlow(
} }
} }
} }
inline fun <reified T> HttpClient.createStandardWebsocketFlow(
url: String,
crossinline conversation: suspend (ByteArray) -> T
) = createStandardWebsocketFlow(this, url, conversation)

View File

@ -0,0 +1,17 @@
package com.insanusmokrassar.postssystem.ktor
import com.soywiz.klock.DateTime
typealias FromToDateTime = Pair<DateTime?, DateTime?>
val FromToDateTime.asFromToUrlPart: QueryParams
get() = mapOf(
"from" to first ?.unixMillis ?.toString(),
"to" to second ?.unixMillis ?.toString()
)
val QueryParams.extractFromToDateTime: FromToDateTime
get() = FromToDateTime(
get("from") ?.toDoubleOrNull() ?.let { DateTime(it) },
get("to") ?.toDoubleOrNull() ?.let { DateTime(it) }
)

View File

@ -0,0 +1,19 @@
package com.insanusmokrassar.postssystem.ktor
import com.insanusmokrassar.postssystem.utils.common.pagination.*
private val numberRegex = Regex("[\\d]{1,10}")
private val pageRegex = Regex("page=${numberRegex.pattern}")
private val sizeRegex = Regex("size=${numberRegex.pattern}")
val Pagination.asUrlQueryParts
get() = mapOf(
"page" to page.toString(),
"size" to size.toString()
)
val Map<String, String?>.extractPagination: Pagination
get() = SimplePagination(
get("page") ?.toIntOrNull() ?: 0,
get("size") ?.toIntOrNull() ?: defaultMediumPageSize
)

View File

@ -0,0 +1,16 @@
package com.insanusmokrassar.postssystem.ktor
typealias QueryParams = Map<String, String?>
val QueryParams.asUrlQuery: String
get() = keys.joinToString("&") { "${it}${get(it) ?.let { value -> "=$value" }}" }
fun String.includeQueryParams(
queryParams: QueryParams
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
val String.parseUrlQuery: QueryParams
get() = split("&").map {
it.split("=").let { pair ->
pair.first() to pair.getOrNull(1)
}
}.toMap()

View File

@ -2,4 +2,4 @@ package com.insanusmokrassar.postssystem.ktor
import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.cbor.Cbor
val standardKtorSerializer = Cbor val standardKtorSerialFormat = Cbor

View File

@ -3,13 +3,9 @@ package com.insanusmokrassar.postssystem.ktor.tests
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
import com.insanusmokrassar.postssystem.ktor.server.createKtorServer import com.insanusmokrassar.postssystem.ktor.server.createKtorServer
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
import io.ktor.application.install import io.ktor.application.install
import io.ktor.application.log
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.cio.websocket.pingPeriod
import io.ktor.http.cio.websocket.timeout
import io.ktor.routing.route
import io.ktor.routing.routing import io.ktor.routing.routing
import io.ktor.websocket.WebSockets import io.ktor.websocket.WebSockets
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -17,7 +13,6 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
import org.junit.Test import org.junit.Test
import java.time.Duration
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNull import kotlin.test.assertNull
@ -33,7 +28,7 @@ class WebsocketsTest {
install(WebSockets) install(WebSockets)
routing { routing {
includeWebsocketHandling(suburl, dataFlow) { includeWebsocketHandling(suburl, dataFlow) {
standardKtorSerializer.dump(Int.serializer(), it) standardKtorSerialFormat.dump(Int.serializer(), it)
} }
} }
}.also { }.also {
@ -50,7 +45,7 @@ class WebsocketsTest {
"$serverUrl/$suburl", "$serverUrl/$suburl",
{ false } // always skip reconnection { false } // always skip reconnection
) { ) {
standardKtorSerializer.load(Int.serializer(), it) standardKtorSerialFormat.load(Int.serializer(), it)
} }
var currentlyCheckingData: Int? = null var currentlyCheckingData: Int? = null

View File

@ -1,8 +1,8 @@
package com.insanusmokrassar.postssystem.markups.core package com.insanusmokrassar.postssystem.markups.core
import com.insanusmokrassar.postssystem.markups.core.utils.* import com.insanusmokrassar.postssystem.markups.core.utils.*
import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
import kotlin.math.min import kotlin.math.min
abstract class MarkupsSystem( abstract class MarkupsSystem(

View File

@ -0,0 +1,3 @@
package com.insanusmokrassar.postssystem.utils.common
typealias UnixMillis = Double

View File

@ -1,4 +1,4 @@
package com.insanusmokrassar.postssystem.utils.repos.pagination package com.insanusmokrassar.postssystem.utils.common.pagination
import kotlin.math.ceil import kotlin.math.ceil

View File

@ -1,4 +1,4 @@
package com.insanusmokrassar.postssystem.utils.repos.pagination package com.insanusmokrassar.postssystem.utils.common.pagination
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package com.insanusmokrassar.postssystem.utils.repos.pagination package com.insanusmokrassar.postssystem.utils.common.pagination
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,7 +1,7 @@
package com.insanusmokrassar.postssystem.utils.repos package com.insanusmokrassar.postssystem.utils.repos
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
interface OneToManyReadKeyValueRepo<Key, Value> : Repo { interface OneToManyReadKeyValueRepo<Key, Value> : Repo {
suspend fun get(k: Key, pagination: Pagination, reversed: Boolean = false): PaginationResult<Value> suspend fun get(k: Key, pagination: Pagination, reversed: Boolean = false): PaginationResult<Value>

View File

@ -1,7 +1,7 @@
package com.insanusmokrassar.postssystem.utils.repos package com.insanusmokrassar.postssystem.utils.repos
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface ReadStandardCRUDRepo<ObjectType, IdType> : Repo { interface ReadStandardCRUDRepo<ObjectType, IdType> : Repo {

View File

@ -1,7 +1,7 @@
package com.insanusmokrassar.postssystem.utils.repos package com.insanusmokrassar.postssystem.utils.repos
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface StandardReadKeyValueRepo<Key, Value> : Repo { interface StandardReadKeyValueRepo<Key, Value> : Repo {

View File

@ -1,8 +1,8 @@
package com.insanusmokrassar.postssystem.utils.repos.exposed package com.insanusmokrassar.postssystem.utils.repos.exposed
import com.insanusmokrassar.postssystem.exposed.commons.paginate import com.insanusmokrassar.postssystem.exposed.commons.paginate
import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
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

@ -1,8 +1,8 @@
package com.insanusmokrassar.postssystem.utils.repos.exposed.keyvalue package com.insanusmokrassar.postssystem.utils.repos.exposed.keyvalue
import com.insanusmokrassar.postssystem.exposed.commons.paginate import com.insanusmokrassar.postssystem.exposed.commons.paginate
import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
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

@ -1,8 +1,8 @@
package com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany package com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany
import com.insanusmokrassar.postssystem.exposed.commons.paginate import com.insanusmokrassar.postssystem.exposed.commons.paginate
import com.insanusmokrassar.postssystem.utils.common.pagination.*
import com.insanusmokrassar.postssystem.utils.repos.OneToManyReadKeyValueRepo import com.insanusmokrassar.postssystem.utils.repos.OneToManyReadKeyValueRepo
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction