From 92ab01ee9de089fa2ad7580814bc799b775a2609 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 7 Jan 2022 23:38:55 +0600 Subject: [PATCH] add storing of content --- .../kotlin/dev/inmo/postssystem/client/DI.kt | 7 +- features/content/binary/server/build.gradle | 3 +- .../server/BinaryServerContentStorage.kt | 85 +++++++++++++ features/content/server/build.gradle | 1 + .../content/server/ServerContentStorage.kt | 2 +- .../server/ServerContentStorageAggregator.kt | 117 ++++++++++++++++++ .../server/ServerContentStorageWrapper.kt | 47 +++++++ .../server/ServerWriteContentStorage.kt | 2 +- features/content/text/server/build.gradle | 1 + .../text/server/TextServerContentStorage.kt | 53 ++++++++ ...esStorage.kt => ClientReadFilesStorage.kt} | 6 +- .../files/common/storage/FilesStorage.kt | 11 +- .../files/common/storage/FullFilesStorage.kt | 8 -- .../files/common/storage/ReadFilesStorage.kt | 9 ++ ...ilesStorage.kt => DiskReadFilesStorage.kt} | 6 +- .../files/server/FilesRoutingConfigurator.kt | 4 +- .../dev/inmo/postssystem/server/Config.kt | 5 + .../java/dev/inmo/postssystem/server/DI.kt | 47 +++++-- 18 files changed, 377 insertions(+), 37 deletions(-) create mode 100644 features/content/binary/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/binary/server/BinaryServerContentStorage.kt create mode 100644 features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageAggregator.kt create mode 100644 features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageWrapper.kt create mode 100644 features/content/text/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/text/server/TextServerContentStorage.kt rename features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/{ClientFilesStorage.kt => ClientReadFilesStorage.kt} (89%) delete mode 100644 features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt create mode 100644 features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/ReadFilesStorage.kt rename features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/{DiskFilesStorage.kt => DiskReadFilesStorage.kt} (93%) diff --git a/client/src/commonMain/kotlin/dev/inmo/postssystem/client/DI.kt b/client/src/commonMain/kotlin/dev/inmo/postssystem/client/DI.kt index 94712f95..909dfff6 100644 --- a/client/src/commonMain/kotlin/dev/inmo/postssystem/client/DI.kt +++ b/client/src/commonMain/kotlin/dev/inmo/postssystem/client/DI.kt @@ -3,8 +3,8 @@ package dev.inmo.postssystem.client import dev.inmo.postssystem.client.ui.fsm.* import dev.inmo.postssystem.features.auth.client.installClientAuthenticator import dev.inmo.postssystem.features.auth.common.* -import dev.inmo.postssystem.features.files.client.ClientFilesStorage -import dev.inmo.postssystem.features.files.common.storage.FilesStorage +import dev.inmo.postssystem.features.files.client.ClientReadFilesStorage +import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.postssystem.features.roles.common.Role import dev.inmo.postssystem.features.roles.common.RolesStorage import dev.inmo.postssystem.features.roles.client.ClientRolesStorage @@ -18,7 +18,6 @@ import dev.inmo.micro_utils.fsm.common.StatesMachine import dev.inmo.micro_utils.fsm.common.dsl.FSMBuilder import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo import dev.inmo.micro_utils.ktor.client.UnifiedRequester -import dev.inmo.micro_utils.ktor.common.standardKtorSerialFormat import dev.inmo.micro_utils.repos.KeyValueRepo import dev.inmo.postssystem.client.settings.DefaultSettings import dev.inmo.postssystem.client.settings.Settings @@ -131,7 +130,7 @@ fun getAuthorizedFeaturesDIModule( single { StatusFeatureClient(get(serverUrlQualifier), get()) } - single { ClientFilesStorage(get(serverUrlQualifier), get(), get()) } + single { ClientReadFilesStorage(get(serverUrlQualifier), get(), get()) } single { UsersStorageKtorClient(get(serverUrlQualifier), get()) } single> { ClientRolesStorage(get(serverUrlQualifier), get(), Role.serializer()) } } diff --git a/features/content/binary/server/build.gradle b/features/content/binary/server/build.gradle index 148d393a..b3a026c6 100644 --- a/features/content/binary/server/build.gradle +++ b/features/content/binary/server/build.gradle @@ -10,7 +10,8 @@ kotlin { commonMain { dependencies { api project(":postssystem.features.content.binary.common") - api project(":postssystem.features.common.server") + api project(":postssystem.features.content.server") + api project(":postssystem.features.files.server") } } } diff --git a/features/content/binary/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/binary/server/BinaryServerContentStorage.kt b/features/content/binary/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/binary/server/BinaryServerContentStorage.kt new file mode 100644 index 00000000..e5bbe4cd --- /dev/null +++ b/features/content/binary/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/binary/server/BinaryServerContentStorage.kt @@ -0,0 +1,85 @@ +package dev.inmo.postssystem.features.content.binary.server + +import dev.inmo.micro_utils.pagination.* +import dev.inmo.micro_utils.repos.UpdatedValuePair +import dev.inmo.postssystem.features.content.binary.common.BinaryContent +import dev.inmo.postssystem.features.content.common.* +import dev.inmo.postssystem.features.content.server.ServerContentStorage +import dev.inmo.postssystem.features.files.common.* +import dev.inmo.postssystem.features.files.common.storage.FilesStorage +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +class BinaryServerContentStorage( + private val filesStorage: FilesStorage +) : ServerContentStorage { + private val FileId.asContentId + get() = ContentId(string) + private val ContentId.asFileId + get() = FileId(string) + private val FullFileInfoStorageWrapper.asRegisteredContent + get() = RegisteredContent( + id.asContentId, + BinaryContent( + fileInfo.name, + fileInfo.mimeType, + fileInfo.byteArrayAllocator + ) + ) + private val BinaryContent.asFullFileInfo + get() = FullFileInfo( + filename, + mimeType, + bytesAllocator + ) + override val deletedObjectsIdsFlow: Flow = filesStorage.deletedObjectsIdsFlow.map { it.asContentId } + override val newObjectsFlow: Flow = filesStorage.newObjectsFlow.map { it.asRegisteredContent } + override val updatedObjectsFlow: Flow = filesStorage.updatedObjectsFlow.map { it.asRegisteredContent } + + override suspend fun create(values: List): List { + return filesStorage.create( + values.map { it.asFullFileInfo } + ).map { it.asRegisteredContent } + } + + override suspend fun deleteById(ids: List) { + filesStorage.deleteById(ids.map { it.asFileId }) + } + + override suspend fun update(id: ContentId, value: BinaryContent): RegisteredContent? { + return filesStorage.update( + id.asFileId, + value.asFullFileInfo + ) ?.asRegisteredContent + } + + override suspend fun update(values: List>): List { + return filesStorage.update( + values.map { (id, content) -> + id.asFileId to content.asFullFileInfo + } + ).map { + it.asRegisteredContent + } + } + + override suspend fun contains(id: ContentId): Boolean { + return filesStorage.contains(id.asFileId) + } + + override suspend fun count(): Long = filesStorage.count() + + override suspend fun getById(id: ContentId): RegisteredContent? { + return filesStorage.getFullFileInfo(id.asFileId) ?.asRegisteredContent + } + + override suspend fun getByPagination(pagination: Pagination): PaginationResult { + return filesStorage.getByPagination(pagination).let { + it.changeResultsUnchecked( + it.results.mapNotNull { + filesStorage.getFullFileInfo(it.id) ?.asRegisteredContent + } + ) + } + } +} diff --git a/features/content/server/build.gradle b/features/content/server/build.gradle index eaa12f15..f079575c 100644 --- a/features/content/server/build.gradle +++ b/features/content/server/build.gradle @@ -11,6 +11,7 @@ kotlin { dependencies { api project(":postssystem.features.content.common") api project(":postssystem.features.common.server") + api project(":postssystem.features.content.server") } } } diff --git a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorage.kt b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorage.kt index ff424af6..75498560 100644 --- a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorage.kt +++ b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorage.kt @@ -3,4 +3,4 @@ package dev.inmo.postssystem.features.content.server import dev.inmo.micro_utils.repos.CRUDRepo import dev.inmo.postssystem.features.content.common.* -interface ServerContentStorage : ServerReadContentStorage, ServerWriteContentStorage, CRUDRepo +interface ServerContentStorage : ServerReadContentStorage, ServerWriteContentStorage, CRUDRepo diff --git a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageAggregator.kt b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageAggregator.kt new file mode 100644 index 00000000..de8812c3 --- /dev/null +++ b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageAggregator.kt @@ -0,0 +1,117 @@ +package dev.inmo.postssystem.features.content.server + +import dev.inmo.micro_utils.pagination.* +import dev.inmo.micro_utils.repos.UpdatedValuePair +import dev.inmo.postssystem.features.content.common.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.Flow + +class ServerContentStorageAggregator( + private val storages: List>, + private val scope: CoroutineScope +) : ServerContentStorage { + override val deletedObjectsIdsFlow: Flow + get() = TODO("Not yet implemented") + override val newObjectsFlow: Flow + get() = TODO("Not yet implemented") + override val updatedObjectsFlow: Flow + get() = TODO("Not yet implemented") + + override suspend fun create(values: List): List { + return values.groupBy { + storages.firstOrNull { storage -> storage.mayHandle(it) } + }.let { + (it - null) as Map, List> + }.flatMap { (storage, content) -> + storage.create(content) + } + } + + override suspend fun deleteById(ids: List) { + storages.map { + scope.launch { it.deleteById(ids) } + }.joinAll() + } + + override suspend fun update(id: ContentId, value: Content): RegisteredContent? { + return storages.mapNotNull { + it.takeIf { it.mayHandle(value) } + }.firstNotNullOfOrNull { it.update(id, value) } + } + + override suspend fun update(values: List>): List { + return values.groupBy { (_, content) -> + storages.firstOrNull { storage -> storage.mayHandle(content) } + }.let { + (it - null) as Map, List>> + }.flatMap { (storage, values) -> + storage.update(values) + } + } + + override suspend fun contains(id: ContentId): Boolean { + val contains = CompletableDeferred() + storages.map { + scope.launch { + if (it.contains(id)) { + contains.complete(true) + } + }.also { job -> + contains.invokeOnCompletion { job.cancel() } + } + }.joinAll() + return if (contains.isCompleted) { + contains.getCompleted() + } else { + return false + } + } + + override suspend fun count(): Long { + return storages.map { + scope.async { + it.count() + } + }.awaitAll().sum() + } + + override suspend fun getById(id: ContentId): RegisteredContent? { + val result = CompletableDeferred() + + storages.map { + scope.launch { + val content = it.getById(id) + if (content != null) { + result.complete(content) + } + }.also { job -> + result.invokeOnCompletion { job.cancel() } + } + }.joinAll() + + return if (result.isCompleted) { + result.getCompleted() + } else { + return null + } + } + + override suspend fun getByPagination( + pagination: Pagination + ): PaginationResult { + val currentResults = mutableListOf() + + for (it in storages) { + val currentPagination = PaginationByIndexes((currentResults.size + pagination.firstIndex), pagination.lastIndex) + val wrapperResults = it.getByPagination(currentPagination) + + currentResults.addAll(wrapperResults.results) + + if (currentResults.size >= pagination.size) { + break + } + } + + return currentResults.createPaginationResult(pagination, count()) + } +} diff --git a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageWrapper.kt b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageWrapper.kt new file mode 100644 index 00000000..463d2e81 --- /dev/null +++ b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerContentStorageWrapper.kt @@ -0,0 +1,47 @@ +package dev.inmo.postssystem.features.content.server + +import dev.inmo.micro_utils.repos.UpdatedValuePair +import dev.inmo.postssystem.features.content.common.* +import kotlinx.coroutines.flow.Flow +import kotlin.reflect.KClass + +class ServerContentStorageWrapper( + private val originalStorage: ServerContentStorage, + private val klass: KClass +): ServerContentStorage, ServerReadContentStorage by originalStorage { + override val deletedObjectsIdsFlow: Flow by originalStorage::deletedObjectsIdsFlow + override val newObjectsFlow: Flow by originalStorage::newObjectsFlow + override val updatedObjectsFlow: Flow by originalStorage::updatedObjectsFlow + + fun mayHandle(content: Content) = klass.isInstance(content) + @Suppress("UNCHECKED_CAST") + private fun asHandlableContent(content: Content) = if (mayHandle(content)) content as T else null + + override suspend fun create(values: List): List { + return originalStorage.create( + values.mapNotNull { + asHandlableContent(it) + } + ) + } + + override suspend fun deleteById(ids: List) = originalStorage.deleteById(ids) + + override suspend fun update(id: ContentId, value: Content): RegisteredContent? { + return originalStorage.update(id, asHandlableContent(value) ?: return null) + } + + override suspend fun update(values: List>): List { + return originalStorage.update( + values.mapNotNull { (id, content) -> + id to (asHandlableContent(content) ?: return@mapNotNull null) + } + ) + } + +} + +inline fun ServerContentStorage.wrap() = ServerContentStorageWrapper( + this, + T::class +) diff --git a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerWriteContentStorage.kt b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerWriteContentStorage.kt index d70e1f9c..fb3de668 100644 --- a/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerWriteContentStorage.kt +++ b/features/content/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/server/ServerWriteContentStorage.kt @@ -3,4 +3,4 @@ package dev.inmo.postssystem.features.content.server import dev.inmo.micro_utils.repos.WriteCRUDRepo import dev.inmo.postssystem.features.content.common.* -interface ServerWriteContentStorage : WriteCRUDRepo +interface ServerWriteContentStorage : WriteCRUDRepo diff --git a/features/content/text/server/build.gradle b/features/content/text/server/build.gradle index 5773b282..69aae06e 100644 --- a/features/content/text/server/build.gradle +++ b/features/content/text/server/build.gradle @@ -11,6 +11,7 @@ kotlin { dependencies { api project(":postssystem.features.content.text.common") api project(":postssystem.features.common.server") + api project(":postssystem.features.content.server") } } } diff --git a/features/content/text/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/text/server/TextServerContentStorage.kt b/features/content/text/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/text/server/TextServerContentStorage.kt new file mode 100644 index 00000000..b54caf58 --- /dev/null +++ b/features/content/text/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/content/text/server/TextServerContentStorage.kt @@ -0,0 +1,53 @@ +package dev.inmo.postssystem.features.content.text.server + +import com.benasher44.uuid.uuid4 +import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo +import dev.inmo.micro_utils.repos.exposed.initTable +import dev.inmo.postssystem.features.content.common.ContentId +import dev.inmo.postssystem.features.content.common.RegisteredContent +import dev.inmo.postssystem.features.content.server.ServerContentStorage +import dev.inmo.postssystem.features.content.text.common.TextContent +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateStatement + +class TextServerContentStorage( + override val database: Database +) : ServerContentStorage, + AbstractExposedCRUDRepo(tableName = "TextContent") { + + val idColumn = text("id") + private val textColumn = text("text") + + override val selectByIds: SqlExpressionBuilder.(List) -> Op = { + idColumn.inList(it.map { it.string }) + } + override val selectById: SqlExpressionBuilder.(ContentId) -> Op = { + idColumn.eq(it.string) + } + override val ResultRow.asObject: RegisteredContent + get() = RegisteredContent( + ContentId(get(idColumn)), + TextContent(get(textColumn)) + ) + + init { + initTable() + } + + override fun insert(value: TextContent, it: InsertStatement) { + it[idColumn] = uuid4().toString() + it[textColumn] = value.text + } + + override fun update(id: ContentId, value: TextContent, it: UpdateStatement) { + it[textColumn] = value.text + } + + override fun InsertStatement.asObject(value: TextContent): RegisteredContent { + return RegisteredContent( + ContentId(get(idColumn)), + TextContent(get(textColumn)) + ) + } +} diff --git a/features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientFilesStorage.kt b/features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientReadFilesStorage.kt similarity index 89% rename from features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientFilesStorage.kt rename to features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientReadFilesStorage.kt index e41fc789..50b208a1 100644 --- a/features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientFilesStorage.kt +++ b/features/files/client/src/commonMain/kotlin/dev/inmo/postssystem/features/files/client/ClientReadFilesStorage.kt @@ -1,7 +1,7 @@ package dev.inmo.postssystem.features.files.client import dev.inmo.postssystem.features.files.common.* -import dev.inmo.postssystem.features.files.common.storage.FilesStorage +import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.repos.ReadCRUDRepo @@ -13,11 +13,11 @@ import io.ktor.client.statement.readBytes import kotlinx.serialization.BinaryFormat import kotlinx.serialization.builtins.nullable -class ClientFilesStorage( +class ClientReadFilesStorage( baseUrl: String, private val client: HttpClient, private val serialFormat: BinaryFormat -) : FilesStorage, ReadCRUDRepo by KtorReadStandardCrudRepo( +) : ReadFilesStorage, ReadCRUDRepo by KtorReadStandardCrudRepo( buildStandardUrl(baseUrl, filesRootPathPart), UnifiedRequester(client, serialFormat), MetaFileInfoStorageWrapper.serializer(), diff --git a/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt b/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt index 90bf5360..06c07ff5 100644 --- a/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt +++ b/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt @@ -1,9 +1,8 @@ package dev.inmo.postssystem.features.files.common.storage -import dev.inmo.postssystem.features.files.common.* -import dev.inmo.micro_utils.repos.ReadCRUDRepo +interface FilesStorage : ReadFilesStorage, WriteFilesStorage -interface FilesStorage : ReadCRUDRepo { - suspend fun getBytes(id: FileId): ByteArray - suspend fun getFullFileInfo(id: FileId): FullFileInfoStorageWrapper? -} +class DefaultFilesStorage( + filesStorage: ReadFilesStorage, + writeFilesStorage: WriteFilesStorage +) : FilesStorage, ReadFilesStorage by filesStorage, WriteFilesStorage by writeFilesStorage diff --git a/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt b/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt deleted file mode 100644 index 6ddc513c..00000000 --- a/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.inmo.postssystem.features.files.common.storage - -interface FullFilesStorage : FilesStorage, WriteFilesStorage - -class DefaultFullFilesStorage( - filesStorage: FilesStorage, - writeFilesStorage: WriteFilesStorage -) : FullFilesStorage, FilesStorage by filesStorage, WriteFilesStorage by writeFilesStorage diff --git a/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/ReadFilesStorage.kt b/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/ReadFilesStorage.kt new file mode 100644 index 00000000..539da47d --- /dev/null +++ b/features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/ReadFilesStorage.kt @@ -0,0 +1,9 @@ +package dev.inmo.postssystem.features.files.common.storage + +import dev.inmo.postssystem.features.files.common.* +import dev.inmo.micro_utils.repos.ReadCRUDRepo + +interface ReadFilesStorage : ReadCRUDRepo { + suspend fun getBytes(id: FileId): ByteArray + suspend fun getFullFileInfo(id: FileId): FullFileInfoStorageWrapper? +} diff --git a/features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskFilesStorage.kt b/features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskReadFilesStorage.kt similarity index 93% rename from features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskFilesStorage.kt rename to features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskReadFilesStorage.kt index c2fe9d5f..d18608af 100644 --- a/features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskFilesStorage.kt +++ b/features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskReadFilesStorage.kt @@ -1,14 +1,14 @@ package dev.inmo.postssystem.features.files.common -import dev.inmo.postssystem.features.files.common.storage.FilesStorage +import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.repos.ReadKeyValueRepo import java.io.File -class DiskFilesStorage( +class DiskReadFilesStorage( private val filesFolder: File, private val metasKeyValueRepo: ReadKeyValueRepo -) : FilesStorage { +) : ReadFilesStorage { private val FileId.file get() = File(filesFolder, string) diff --git a/features/files/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/server/FilesRoutingConfigurator.kt b/features/files/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/server/FilesRoutingConfigurator.kt index 04df8b57..cf08a81e 100644 --- a/features/files/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/server/FilesRoutingConfigurator.kt +++ b/features/files/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/server/FilesRoutingConfigurator.kt @@ -13,11 +13,11 @@ import io.ktor.routing.* import kotlinx.serialization.builtins.nullable class FilesRoutingConfigurator( - private val filesStorage: FilesStorage, + private val filesStorage: ReadFilesStorage, private val writeFilesStorage: WriteFilesStorage?, private val unifierRouter: UnifiedRouter ) : ApplicationRoutingConfigurator.Element { - constructor(fullFilesStorage: FullFilesStorage, unifierRouter: UnifiedRouter) : this(fullFilesStorage, fullFilesStorage, unifierRouter) + constructor(filesStorage: FilesStorage, unifierRouter: UnifiedRouter) : this(filesStorage, filesStorage, unifierRouter) override fun Route.invoke() { authenticate { diff --git a/server/src/main/java/dev/inmo/postssystem/server/Config.kt b/server/src/main/java/dev/inmo/postssystem/server/Config.kt index 1bed1c08..c21bcd6e 100644 --- a/server/src/main/java/dev/inmo/postssystem/server/Config.kt +++ b/server/src/main/java/dev/inmo/postssystem/server/Config.kt @@ -18,4 +18,9 @@ data class Config( ) { val filesFolderFile: File get() = File(filesFolder) + + val commonFilesFolder: File + get() = File(filesFolderFile, "common").also { it.mkdirs() } + val binaryFilesFolder: File + get() = File(filesFolderFile, "binary_content").also { it.mkdirs() } } diff --git a/server/src/main/java/dev/inmo/postssystem/server/DI.kt b/server/src/main/java/dev/inmo/postssystem/server/DI.kt index 53ceed25..f6a7cd8d 100644 --- a/server/src/main/java/dev/inmo/postssystem/server/DI.kt +++ b/server/src/main/java/dev/inmo/postssystem/server/DI.kt @@ -26,9 +26,12 @@ import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo import dev.inmo.postssystem.features.common.common.* import dev.inmo.postssystem.features.content.binary.common.BinaryContentSerializerModuleConfigurator -import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator -import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator +import dev.inmo.postssystem.features.content.binary.server.BinaryServerContentStorage +import dev.inmo.postssystem.features.content.common.* +import dev.inmo.postssystem.features.content.server.ServerContentStorage +import dev.inmo.postssystem.features.content.server.ServerContentStorageAggregator import dev.inmo.postssystem.features.content.text.common.TextContentSerializerModuleConfigurator +import dev.inmo.postssystem.features.content.text.server.TextServerContentStorage import dev.inmo.postssystem.features.publication.server.PublicationManager import dev.inmo.postssystem.features.publication.server.PublicationTarget import dev.inmo.postssystem.targets.telegram.publication.server.PublicationTargetTelegram @@ -70,8 +73,12 @@ fun getDIModule( val config = configJson.decodeFromString(Config.serializer(), File(args.first()).readText()) val originalFilesMetasKeyValueRepoQualifier = StringQualifier("OriginalFilesMetaKV") - val filesMetasKeyValueRepoQualifier = StringQualifier("FilesMetaKV") - val filesFolderQualifier = StringQualifier("filesFolder") + val binaryOriginalFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryOriginalFilesMetaKV") + val commonFilesMetasKeyValueRepoQualifier = StringQualifier("CommonFilesMetaKV") + val binaryFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryFilesMetaKV") + val filesFolderQualifier = StringQualifier("rootFilesFolder") + val commonFilesFolderQualifier = StringQualifier("commonFilesFolder") + val binaryFilesFolderQualifier = StringQualifier("binaryFilesFolder") val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory") return module { @@ -100,20 +107,25 @@ fun getDIModule( singleWithBinds { get().databaseConfig } singleWithBinds { get().authConfig } singleWithBinds(filesFolderQualifier) { get().filesFolderFile } + singleWithBinds(commonFilesFolderQualifier) { get().commonFilesFolder } + singleWithBinds(binaryFilesFolderQualifier) { get().binaryFilesFolder } singleWithBinds { get().database } singleWithBinds(originalFilesMetasKeyValueRepoQualifier) { ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "FileIdsToMetas") } - singleWithBinds(filesMetasKeyValueRepoQualifier) { + singleWithBinds(binaryOriginalFilesMetasKeyValueRepoQualifier) { + ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "BinaryContentFileIdsToMetas") + } + singleWithBinds(commonFilesMetasKeyValueRepoQualifier) { MetasKeyValueRepo( get(), get(originalFilesMetasKeyValueRepoQualifier) ) } - single { DiskFilesStorage(get(filesFolderQualifier), get(filesMetasKeyValueRepoQualifier)) } - single { WriteDistFilesStorage(get(filesFolderQualifier), get(filesMetasKeyValueRepoQualifier)) } - single { DefaultFullFilesStorage(get(), get()) } + single { DiskReadFilesStorage(get(commonFilesFolderQualifier), get(commonFilesMetasKeyValueRepoQualifier)) } + single { WriteDistFilesStorage(get(commonFilesFolderQualifier), get(commonFilesMetasKeyValueRepoQualifier)) } + single { DefaultFilesStorage(get(), get()) } singleWithBinds { ExposedUsersStorage(get()) } singleWithBinds { exposedUsersAuthenticator(get(), get()) } @@ -142,6 +154,25 @@ fun getDIModule( factory { baseScope.LinkedSupervisorScope() } + // Content storages + val binaryStorageFilesQualifier = StringQualifier("binaryContentFiles") + singleWithBinds(binaryFilesMetasKeyValueRepoQualifier) { + MetasKeyValueRepo( + get(), + get(binaryOriginalFilesMetasKeyValueRepoQualifier) + ) + } + single(binaryStorageFilesQualifier) { + DefaultFilesStorage( + DiskReadFilesStorage(get(binaryFilesFolderQualifier), get(binaryFilesMetasKeyValueRepoQualifier)), + WriteDistFilesStorage(get(binaryFilesFolderQualifier), get(binaryFilesMetasKeyValueRepoQualifier)) + ) + } + singleWithRandomQualifier { BinaryServerContentStorage(get(binaryStorageFilesQualifier)) } + singleWithRandomQualifier { TextServerContentStorage(get()) } + + single> { ServerContentStorageAggregator(getAll(), get()) } + // Routing configurators singleWithBinds { FilesRoutingConfigurator(get(), null, get()) } singleWithBinds { StatusRoutingConfigurator }