Opencode Event 表写入优化方案

目标 :减少 event 表写入量,不改 Schema,不改 UI,不破坏重放机制

版本 :基于 D:\agent\opencode(dev 分支,v1.17.18)

2026/7/12


一、设计原则

  • 不改 Schema --- 不新增事件类型,不修改表结构

  • 不改 UI --- Web/CLI 消费端保持完全不动

  • 最小改动 --- 聚焦合并写入操作,不做架构层面的重写


二、优化一:合并 step-finish + cleanup

现状

processor.ts 中,每个 LLM turn 至少产生 2 次 updateMessage 调用:

  1. step-finish (L456):写入 finish、cost、tokens

  2. cleanup (L596):写入 time.completed

加上 prompt.ts 中创建 assistant message 的那次写入,同一条消息在 event 表中留下 3 条 message.updated.1 记录。

修改方案

让 step-finish 承担 time.completed 的写入,cleanup 仅在异常场景下兜底:

typescript

复制代码
// step-finish 分支 (L456):
ctx.assistantMessage.time.completed = Date.now()  // 新增
yield* session.updateMessage(ctx.assistantMessage)

// cleanup 分支 (L596):
// 如果已完成则跳过,仅作兜底
if (!ctx.assistantMessage.time.completed) {
  ctx.assistantMessage.time.completed = Date.now()
  yield* session.updateMessage(ctx.assistantMessage)
}

效果

指标 改前 改后
正常流程写入次数 2 次 1 次
异常流程覆盖 ✅ ✅(cleanup 兜底)

风险等级:低 --- cleanup 保留完整兜底逻辑,异常场景不受影响


三、优化二:合并创建 + 首次更新(暂缓)

现状

prompt.ts:1201 创建 assistant message 时触发一次 updateMessage,此时消息内容为空(content 为空,cost=0,tokens=0),仅为占位记录。随后 processor.ts:456 的 step-finish 再次更新,写入实际数据。

改造思路

创建时不立即发布 durable event ,仅在内存中维护消息记录,延迟到 step-finish 阶段再统一写入。

决策

暂不实施 。该改动涉及 prompt.ts 与 processor.ts 之间的交互逻辑调整,改动面较大,收益与优化一重叠,优先级靠后。


四、优化三:PartUpdated 去 durable(需验证后实施)

现状

PartUpdated(message.part.updated.1)在 event 表中占据 260,911 行 / 1,047 MB ,约占总数据量的 68%。

每条 updatePart 调用都会将完整的 part JSON 写入 event 表。streaming 过程中,text-start、text-end、reasoning-start、reasoning-end、step-start、step-finish 等事件都会触发写入。

而 PartDelta(message.part.delta)已经采用了非 durable 的设计,可作为参照。

修改方案

schema/src/v1/session.ts:612 中移除 PartUpdated 的 durable 标记:

typescript

复制代码
PartUpdated: define({
  type: "message.part.updated",
  // 去掉 ...options 中的 durable 配置
  schema: {
    sessionID: SessionID,
    part: Part,
    time: Schema.Finite,
  },
}),

安全性验证

需要确认两点:

  1. Web UI 会话重放是否依赖 event 表中的 PartUpdated?

    检查 packages/app/src/context/global-sync/event-reducer.ts:该文件处理 message.updated 和 session.updated,不处理 message.part.updated。

  2. V2 sync 是否以 event 表为源?

    检查 packages/app/src/context/server-session.ts:786 的 apply 方法:同样只处理 message.updated,不处理 part.updated。

结论 :PartUpdated 的 event 表行对 Web UI 没有实际消费价值,UI 依赖的是 MessageTable 和 live stream。

效果

指标 数值
消除现有行数 260,911 行(存量不删,但不再增长)
消除数据量 1,047 MB(不再增量)

风险等级:中高 --- 需充分验证 GlobalBus 推送路径是否依赖 event 表写入(初步判断不依赖)


五、优先级

顺序 优化项 效果 风险 改动量 状态
1 优化一:合并 finish+cleanup 省 50% 的 message.updated.1 低 2 行 立即执行
2 优化三:PartUpdated 去 durable 省 68% 的 event 行 中高 1 行 先验证后执行
3 优化二:合并创建+首次更新 省 33% 的 message.updated.1 中 较大 暂缓

六、验证步骤

优化三验证流程

  1. grep 全仓搜索 PartUpdated 的消费者,确认无 projector 或 reducer 依赖

  2. 在测试环境将 PartUpdated 改为非 durable,运行一个完整 LLM turn

  3. 检查 Web UI 的会话重放是否正常(消息内容、part 顺序、streaming 效果)

  4. 对比 event 表增量,确认减少量符合预期

验收标准

  • □ 优化一部署后,正常流程每条 assistant 消息从 2 次更新减少为 1 次

  • □ 优化三部署后,event 表日增量减少 60% 以上

  • □ Web UI 所有功能(消息展示、会话重放、streaming 效果)无异常

  • □ CLI 交互无异常


七、执行清单

  1. 优化一 --- 修改 processor.ts,2 行改动,低风险,立即上线

  2. 验证优化三 --- grep PartUpdated 消费者,确认无依赖

  3. 优化三 --- 修改 session.ts,1 行改动,验证后上线

完成后,跑一个完整的 LLM turn,对比 event 表增量即可验证效果。预计三项全部落地后,event 表整体写入量可减少 60%-70%。

相关推荐
段一凡-华北理工大学2 小时前
工业智能体:从Codex/Claude到项目实战~系列文章06:一张蓝图看懂“工业智能体×高炉炼铁“
人工智能·claude·codex·工业智能体·高炉炼铁智能化·高炉智能体技术栈
怕浪猫2 小时前
十个人,630 万订阅:一张 AI 学习清单里的五种老师
人工智能
JonaHu2 小时前
5分钟搭建帮你赚钱的 AI API 网站:从品牌门户到客户 Key 交付
人工智能·api·开发者·ai创业·acedatacloud
Csvn3 小时前
模型挂了全站 502?降级链让它先保住“有响应”(R04)
人工智能·aigc·agent
isNotNullX3 小时前
仓储管理最全框架:6大流程、8项指标、10个管理动作、12个常见问题
大数据·人工智能
不吃紫菜3 小时前
LangGraph 体系实战(下):中断恢复、流式、子图与设计模式
ai
小白菜004 小时前
AI的理解
人工智能·机器学习
科技苑4 小时前
C++ CAS与ABA问题详解,无锁编程的经典陷阱怎么解决?
c++·人工智能
DFT计算杂谈4 小时前
可DIY布里渊区图像绘制编辑器
人工智能·机器学习·语言模型·矩阵·编辑器