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

org.jetbrains.exposed.dao.EntityHook.kt Maven / Gradle / Ivy

There is a newer version: 0.57.0
Show newest version
package org.jetbrains.exposed.dao

import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.transactionScope
import java.util.Deque
import java.util.concurrent.ConcurrentLinkedDeque
import java.util.concurrent.ConcurrentLinkedQueue

enum class EntityChangeType {
    Created,
    Updated,
    Removed;
}

data class EntityChange(
    val entityClass: EntityClass<*, Entity<*>>,
    val entityId: EntityID<*>,
    val changeType: EntityChangeType,
    val transactionId: String
)

fun , T : Entity> EntityChange.toEntity(): T? = (entityClass as EntityClass).findById(entityId as EntityID)

fun , T : Entity> EntityChange.toEntity(klass: EntityClass): T? {
    if (!entityClass.isAssignableTo(klass)) return null
    @Suppress("UNCHECKED_CAST")
    return toEntity()
}

private val Transaction.unprocessedEvents: Deque by transactionScope { ConcurrentLinkedDeque() }
private val Transaction.entityEvents: Deque by transactionScope { ConcurrentLinkedDeque() }
private val entitySubscribers = ConcurrentLinkedQueue<(EntityChange) -> Unit>()

object EntityHook {
    fun subscribe(action: (EntityChange) -> Unit): (EntityChange) -> Unit {
        entitySubscribers.add(action)
        return action
    }

    fun unsubscribe(action: (EntityChange) -> Unit) {
        entitySubscribers.remove(action)
    }
}

fun Transaction.registerChange(entityClass: EntityClass<*, Entity<*>>, entityId: EntityID<*>, changeType: EntityChangeType) {
    EntityChange(entityClass, entityId, changeType, id).let {
        if (unprocessedEvents.peekLast() != it) {
            unprocessedEvents.addLast(it)
            entityEvents.addLast(it)
        }
    }
}

fun Transaction.alertSubscribers() {
    while (true) {
        val event = unprocessedEvents.pollFirst() ?: break
        entitySubscribers.forEach { it(event) }
    }
}

fun Transaction.registeredChanges() = entityEvents.toList()

fun  withHook(action: (EntityChange) -> Unit, body: () -> T): T {
    EntityHook.subscribe(action)
    try {
        return body().apply {
            TransactionManager.current().commit()
        }
    } finally {
        EntityHook.unsubscribe(action)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy