框架生命周期与元事件流
编写一个优秀的常驻插件,绝不仅仅是“有人发消息就回一句”这么简单哦!什么时候初始化后台巡检协程?Bot 断线重连后如何恢复?这些都要交给生命周期系统。
Eridanus 的事件体系由底层 SDK(developTools/event/)定义,并由框架核心 ExtendBot 进行全局生命周期流控制。
1. 核心生命周期时序
text
[主进程启动]
↓
[YAMLManager 加载全部配置]
↓
[PluginManager 扫描并装载插件 main(bot, config)]
↓
[WebSocket 建立连接并鉴权成功]
↓
[广播 LifecycleMetaEvent (sub_type="enable" / "connect")] ← 适合在此拉起常驻定时任务与轮询
↓
[持续消息监听与事件派发循环 (GroupMessageEvent / PrivateMessageEvent...)]
↓
[进程优雅退出或断开连接]2. 监听 LifecycleMetaEvent 实现后台协程自启动
许多功能(例如 B 站动态轮询、Git 更新检查、空间保活、定时清理临时文件)需要在机器人启动后自动拉起一个死循环协程。
千万不要在 def main(bot, config): 里直接写 asyncio.run() 或者无休止 while True(这会直接卡死主线程插件加载过程!)。正确的姿势是监听生命周期元事件:
python
import asyncio
from developTools.event.events import LifecycleMetaEvent
# 定义全局后台任务句柄,防止热重载时重复启动多份任务
background_task = None
async def my_worker_loop(bot, config):
bot.logger.info("后台定时巡检任务已启动~")
while True:
try:
# 业务轮询逻辑
await asyncio.sleep(60)
except asyncio.CancelledError:
bot.logger.info("后台任务收到取消信号,优雅退出...")
break
except Exception as e:
bot.logger.error(f"后台任务异常: {e}")
await asyncio.sleep(5)
def main(bot, config):
@bot.on(LifecycleMetaEvent)
async def on_lifecycle(event: LifecycleMetaEvent):
global background_task
# 仅在 Bot 建立连接就绪阶段启动后台任务
if background_task is None or background_task.done():
background_task = asyncio.create_task(my_worker_loop(bot, config))3. ExtendBot 框架级过滤机制
框架派发给插件的事件已经过 ExtendBot(framework_common/framework_util/websocket_fix.py)的三重过滤:
- 黑名单过滤:发信人 QQ 或群号如果在
black_and_white_list.yaml的黑名单中,消息直接在最底层丢弃,永远不会触发插件逻辑; - 白名单模式:如果开启了全局群白名单,非白名单群的消息一律静默忽略;
- 执行耗时监控 (HandlerMonitor):每个插件回调的执行时间均受监控,如果某个插件阻塞超过设定的秒数(默认 10 秒),日志会输出黄色警告并附带插件文件路径,帮助你快速定位慢查询或网络卡死问题!