jvmMain.dev.inmo.micro_utils.repos.exposed.AbstractExposedWriteCRUDRepo.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of micro_utils.repos.exposed-jvm Show documentation
Show all versions of micro_utils.repos.exposed-jvm Show documentation
It is set of projects with micro tools for avoiding of routines coding
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)
}
}
}