持续会话 Continuous Session
概述
在进行业务编写时,时常会遇到需要继续连续对话的场景,例如:
如上案例,用户首先发出第一个指令 绑定账户 ,使bot进入等待接受“账户”的状态, 随即接受后续绑定后完成状态。
想要实现这个功能的方式很多,例如最基础的可以通过状态机来完成。 但是当这个流程开始逐步变得复杂,在大量的状态面前手动实现一个状态机就会显得十分繁琐。
这时候,协程就会体现出它的作用。
而持续会话模块 (simbot-extension-continuous-session) 便基于异步与协程对持续会话的封装与实现。
安装
持续会话是一个独立的扩展模块,你需要额外添加它的依赖并配置它。
添加依赖
implementation("love.forte.simbot.extension:simbot-extension-continuous-session:4.15.0")如果使用 Java 而不配合使用 Gradle 的
kotlin插件, 那么你需要指定依赖的后缀为-jvm。implementation("love.forte.simbot.extension:simbot-extension-continuous-session-jvm:4.15.0")implementation 'love.forte.simbot.extension:simbot-extension-continuous-session:4.15.0'如果使用 Java 而不配合使用 Gradle 的
kotlin插件, 那么你需要指定依赖的后缀为-jvm。implementation 'love.forte.simbot.extension:simbot-extension-continuous-session-jvm:4.15.0'<dependency> <groupId>love.forte.simbot.extension</groupId> <artifactId>simbot-extension-continuous-session-jvm</artifactId> <version>4.15.0</version> </dependency>配置
当前扩展提供的主要入口是
EventContinuousSessionContext。它是一个
Plugin, 并且不会通过 SPI 自动安装, 因此需要你显式install(...):launchSimpleApplication { install(EventContinuousSessionContext) { // 可选:为持续会话配置额外协程上下文 coroutineContext = Dispatchers.Default } }在 Spring Boot 中同样需要显式安装, 可以通过
SimbotPluginInstaller完成:@Component open class ContinuousSessionInstaller : SimbotPluginInstaller { override fun install(installer: PluginInstaller) { installer.install(EventContinuousSessionContext) { coroutineContext = Dispatchers.Default } } }
核心类型
- ContinuousSessionContext<T, R>
通用持续会话上下文。
T是“推送进来的事件值”,R是“本次推送返回的结果值”。- EventContinuousSessionContext
面向 simbot 事件系统的现成实现, 固定把
T设为Event、R设为EventResult。- ContinuousSessionKey<C>
一个会话的唯一标识。 当前实现中还提供了一个简单实现:
UnitContinuousSessionKey。- InSession
持续会话内部实际执行的逻辑体。 Java 侧可通过
InSessions.block(...)、InSessions.async(...)、InSessions.mono(...)构造。
冲突策略
创建 session 时,源码中支持三种冲突策略:
FAILURE: 已存在同 key 且仍活跃的 session 时抛出ConflictSessionKeyExceptionREPLACE: 取消旧 session,用新 session 替换EXISTING: 直接返回旧 session,忽略新的创建请求
Kotlin 示例
如果你希望在同一个会话里做多轮校验, 还可以使用:
awaitWith { ... }multipleAwaitWith { ... }awaitValue(...)
Java 风格
Java 下推荐优先使用异步风格的 InSessions.async(...); 如果你的逻辑确实需要阻塞式写法, 源码文档也明确建议使用虚拟线程调度器或至少隔离调度器。
在构造 InSession 时可选:
InSessions.async(...)InSessions.block(...)InSessions.mono(...)
其中 mono(...) 依赖 kotlinx-coroutines-reactor 运行时支持。