实现事件推送
当你有了事件,那么就将其发射。
事件处理器
在simbot标准API中定义了一个用于处理事件的事件处理器 EventProcessor
, 它的作用是由 Application
提供给外部(例如组件),使其拥有推送事件的能力。
我们首先来简单看一下 EventProcessor
的简化版定义:
可以看到, EventProcessor
的主要作用就是:通过 push
推送一个事件 Event
, 然后得到所有事件监听函数(EventListener
)的处理结果流 Flow<EventResult>
。
获取并保存
在介绍用法之前,先讲一下如何获取 EventProcessor
。
Plugin / BotManager 内获取
EventProcessor
在构建阶段中,从开始构建 Plugin
这个阶段开始可以被获取到。 其中, BotManager
的构建就属于这个阶段。
当你的 Plugin
或 BotManager
实现需要使用到事件推送的能力时, 你可以在注册它们的时候从 PluginConfigureContext
获取到 EventDispatcher
。
以一个 BotManager
为例:
外部获取
当 Application
被构建完成后,你可以在直接在 Application
中获取到 EventDispatcher
。
使用
事件推送
一个最简单的使用例子:
在 Java 中,我们为 EventProcessor
提供了一些异步友好的兼容API。
首先, push
函数本身并非挂起函数,因此你可以直接调用它并得到 Flow
的结果。
但是Java中想要直接处理 Flow
就有些困难了。 举个例子,你可以借助 kotlinx-coroutines-reactor
将 Flow
转为 Flux
。
或者直接丢给一个作用域 CoroutineScope
在异步中执行:
除了上面直接借助 EventProcessor
自身的API以外, 我们还使用 EventProcessors
提供若干静态API来辅助使用。
调度器
当执行 EventProcessor.push
时,其内部执行事件处理逻辑时的调度器是在构建 Application
的时候被决定的
因此,通过 push
得到的结果无法影响上游的调度器。例如,以上述代码为基准,再追加以下代码:
那么,用于处理事件的监听函数会在 Dispatcher.IO
中被异步调度, 而在最后的 collect
时会被 MyCustomDispatcher
调度。
冷流与同步
由上可知,虽然默认的事件调度器的实现是冷流 ,即你不去收集则不会真正地执行事件处理, 但是因为可以配置调度器,因此它并非是一条一条地同步处理的。
考虑如下这组代码:
假设其中一共注册了5个事件的监听函数,每个函数都会输出一段控制台文本,那么二者的输出则有可能是:
因此,虽然 push
后使用了 take(3)
限制了条数, 但是它无法保证能够控制真实的事件处理次数。
结果筛选
作为一个插件,通常情况下我们需要对返回的 EventResult
结果流做一些处理。 一个最常见的场景:我们要将返回了错误的结果以日志的形式输出。
EventResult
包括了所有执行了的事件监听函数的执行结果,包括错误的结果。 在标准API中,我们约定如果类型为 StandardEventResult.Error
则将其视为一个执行失败的结果 (内部的异常处理也会将出现的错误包装为此),因此你可以在出现此类型时做一些处理:
我们提供了一些简化操作的API。例如,你可以使用 onEachError { ... }
来改写上面的代码: