All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.dev.inmo.micro_utils.repos.exposed.AbstractExposedWriteCRUDRepo.kt Maven / Gradle / Ivy

There is a newer version: 0.22.2
Show newest version
package dev.inmo.micro_utils.repos.exposed

import dev.inmo.micro_utils.repos.UpdatedValuePair
import dev.inmo.micro_utils.repos.WriteCRUDRepo
import kotlinx.coroutines.flow.*
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateStatement
import org.jetbrains.exposed.sql.transactions.transaction

abstract class AbstractExposedWriteCRUDRepo(
    flowsChannelsSize: Int = 0,
    tableName: String = "",
    replyCacheInFlows: Int = 0
) :
    AbstractExposedReadCRUDRepo(tableName),
    ExposedCRUDRepo,
    WriteCRUDRepo
{
    protected val _newObjectsFlow = MutableSharedFlow(replyCacheInFlows, flowsChannelsSize)
    protected val _updatedObjectsFlow = MutableSharedFlow(replyCacheInFlows, flowsChannelsSize)
    protected val _deletedObjectsIdsFlow = MutableSharedFlow(replyCacheInFlows, flowsChannelsSize)
    @Deprecated("Renamed", ReplaceWith("_newObjectsFlow"))
    protected val newObjectsChannel = _newObjectsFlow
    @Deprecated("Renamed", ReplaceWith("_updatedObjectsFlow"))
    protected val updateObjectsChannel = _updatedObjectsFlow
    @Deprecated("Renamed", ReplaceWith("_deletedObjectsIdsFlow"))
    protected val deleteObjectsIdsChannel = _deletedObjectsIdsFlow

    override val newObjectsFlow: Flow = _newObjectsFlow.asSharedFlow()
    override val updatedObjectsFlow: Flow = _updatedObjectsFlow.asSharedFlow()
    override val deletedObjectsIdsFlow: Flow = _deletedObjectsIdsFlow.asSharedFlow()

    protected abstract fun InsertStatement.asObject(value: InputValueType): ObjectType
    abstract val selectByIds: SqlExpressionBuilder.(List) -> Op

    protected abstract fun insert(value: InputValueType, it: InsertStatement)
    protected abstract fun update(id: IdType, value: InputValueType, it: UpdateStatement)

    protected open suspend fun onBeforeCreate(value: List) {}
    private fun createWithoutNotification(value: InputValueType): ObjectType {
        return transaction(database) {
            insert { insert(value, it) }.asObject(value)
        }
    }

    override suspend fun create(values: List): List {
        onBeforeCreate(values)
        return transaction(db = database) {
            values.map { value -> createWithoutNotification(value) }
        }.onEach {
            _newObjectsFlow.emit(it)
        }
    }

    protected open suspend fun onBeforeUpdate(value: List>) {}
    private fun updateWithoutNotification(id: IdType, value: InputValueType): ObjectType? {
        return transaction(db = database) {
            update(
                {
                    selectById(this, id)
                }
            ) {
                update(id, value, it)
            }
        }.let {
            if (it > 0) {
                transaction(db = database) {
                    select {
                        selectById(this, id)
                    }.limit(1).firstOrNull() ?.asObject
                }
            } else {
                null
            }
        }
    }

    override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
        onBeforeUpdate(listOf(id to value))
        return updateWithoutNotification(id, value).also {
            if (it != null) {
                _updatedObjectsFlow.emit(it)
            }
        }
    }
    override suspend fun update(values: List>): List {
        onBeforeUpdate(values)
        return (
            transaction(db = database) {
                values.map { (id, value) -> updateWithoutNotification(id, value) }
            }.filterNotNull()
        ).onEach {
            _updatedObjectsFlow.emit(it)
        }
    }
    protected open suspend fun onBeforeDelete(ids: List) {}
    override suspend fun deleteById(ids: List) {
        onBeforeDelete(ids)
        transaction(db = database) {
            val deleted = deleteWhere(null, null) {
                selectByIds(ids)
            }
            if (deleted == ids.size) {
                ids
            } else {
                ids.filter {
                    select { selectById(it) }.limit(1).none()
                }
            }
        }.forEach {
            _deletedObjectsIdsFlow.emit(it)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy