任务事件系统

本章将介绍如何注册任务事件以实现任务的事件监听和处理。

任务事件插件的使用场景和创建方法

在Kronos中,任务事件插件用于在任务执行的不同阶段触发特定的事件。

这些事件可以帮助我们监控任务的执行情况,或者在任务执行的不同阶段执行特定的操作。

Kronos 事件中可以获取任务的 operationType、SQL 文本、参数 Map、结构化 statement 以及当前 KronosDataSourceWrapper。 通过监听这些事件,我们可以在任务执行的不同阶段执行特定操作,比如拦截任务、记录日志、发送通知或检查任务内容。

DataGuardPlugin 是通过任务事件插件机制实现的内置保护能力。自增主键 ID 的读取属于 insert 执行流程。

创建任务事件插件

创建一个类或对象来实现TaskEventPlugin接口,即可实现一个任务事件插件。

您可以通过实现以下方法来定义任务事件插件的行为:

为什么没有单独的doBeforeUpsert事件?

任务事件插件只有 query 回调和 action 回调。普通 upsert() 会先触发匹配查询,再触发 insert 或 update 操作分支;onConflict() upsert 会作为 operationType = KOperationType.UPSERT 的 action 任务触发。

任务函数的类型为QueryTaskEvent?或ActionTaskEvent?,您可以将它们设置为null以禁用对应的事件。

示例

以下是一个简单的示例,定义了一个简单的任务事件插件实现,它会在任务执行前后打印一些日志信息:

kotlin

import com.kotlinorm.beans.task.registerTaskEventPlugin
import com.kotlinorm.beans.task.unregisterTaskEventPlugin
import com.kotlinorm.enums.KOperationType
import com.kotlinorm.interfaces.TaskEventPlugin

class MyTaskEventPlugin : TaskEventPlugin {
    override val doBeforeQuery = { task, wrapper ->
        println("Before query: ${task.operationType} on ${wrapper.dbType}")
        println("SQL: ${task.sql}")
    }
    override val doAfterQuery = { task, wrapper ->
        println("Query finished with params: ${task.paramMap}")
    }
    override val doBeforeAction = { task, wrapper ->
        println("DBType: ${wrapper.dbType}")
        println("Before action: ${task.operationType}")
        println("SQL: ${task.sql}")
    }
    override val doAfterAction = { task, wrapper ->
        when (task.operationType) {
            KOperationType.INSERT -> {
                println("Inserted with params: ${task.paramMap}")
            }
            KOperationType.UPDATE -> {
                println("Updated with params: ${task.paramMap}")
            }
            KOperationType.UPSERT -> {
                println("Upsert with params: ${task.paramMap}")
            }
            else -> {
                println("Action ${task.operationType} completed")
            }
        }
    }

    private var loaded = false // 是否已加载插件
    var enabled: Boolean // 是否启用
        get() = loaded
        set(value) {
            loaded = value
            if (value) {
                registerTaskEventPlugin(this)
            } else {
                unregisterTaskEventPlugin(this)
            }
        }
}

update 任务的可观察输出形态如下:

result

Before action: UPDATE
SQL: UPDATE `user` SET `name` = :nameNew WHERE `id` = :id
Updated with params: {nameNew=Ada, id=1}