原理详解:读模型与事件日志如何做到零漂移)
T3 Code 投影器Projector原理详解读模型与事件日志如何做到零漂移【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3codeT3 Code 是面向 AI 编程代理的多端服务端运行时。它的状态层采用事件溯源Event Sourcing架构客户端只发命令服务端把命令变成追加式事件日志再由投影器Projector把事件逐条应用到读模型上。本文用最小化的代码视角拆解 T3 Code 的投影器如何让读模型与事件日志做到零漂移——即任何时刻界面看到的状态永远和持久化的日志精确一致。事件溯源为什么需要投影器传统架构里改状态 改数据库行。T3 Code 反其道而行状态不可变只追加事件。整体链路是详见 docs/internals/overview.md客户端派发类型化命令如thread.create、thread.turn.start引擎用纯函数 decider.ts 从「命令 当前状态」推导出新事件事件被追加进事件存储同时由投影器应用到内存读模型和持久化投影表提交后新读模型整体切换并通过订阅推送给客户端。官方架构文档对此一句话总结服务端不直接修改应用状态。客户端派发类型化命令引擎将其变成持久化事件投影projections推导出读模型。内存读模型一个纯函数 projectEventprojector.ts 的核心是一个纯函数projectEvent(model, event)输入旧读模型 一条事件输出新读模型。它没有任何 I/O行为完全可测试见 projector.test.ts。几个关键设计Schema 解码每个事件负载都先用 Effect Schema 解码decodeForEvent脏数据在进入状态之前就被拦截错误带有事件类型:字段的上下文前向兼容switch的default分支直接返回原模型——遇到未知事件类型不会崩溃未来新增事件不会让旧版本投影器抛异常权威信号回合turn是否结束以会话状态离开running为准settledTurnStateForSessionStatus后续的 checkpoint 工作不会改写回合何时结束这一事实有界内存消息上限 2000 条、checkpoint 上限 500 条MAX_THREAD_MESSAGES/MAX_THREAD_CHECKPOINTS保证读模型体积可控。持久化投影管线9 个投影器 游标内存读模型解决当下读得快持久化投影解决重启不丢状态。Layers/ProjectionPipeline.ts 注册了 9 个命名投影器ORCHESTRATION_PROJECTOR_NAMES投影器落库表projection.projectsprojection_projectsprojection.threadsprojection_threadsprojection.thread-messagesprojection_thread_messagesprojection.thread-activitiesprojection_thread_activitiesprojection.thread-sessionsprojection_thread_sessionsprojection.thread-turnsprojection_turnsprojection.checkpoints—由 turns 表承载projection.pending-approvalsprojection_pending_approvalsprojection.thread-proposed-plansprojection_thread_proposed_plans这些表全部定义在 Migrations/005_Projections.ts。零漂移的第一个关键在runProjectorForEvent投影器的写操作和游标更新在同一个 SQL 事务里完成。每个投影器处理完一条事件后把last_applied_sequence写入projection_state表实现见 Layers/ProjectionState.ts。这意味着不存在投影写了、游标没写的中间态。第二个关键顺序确定性。projectEvent用concurrency: 1串行执行所有投影器bootstrap阶段也是concurrency: 1逐个投影器回放。重启时bootstrapProjector从该投影器自己的游标处继续回放事件日志eventStore.readFromSequence——每个投影器可以独立落后、独立追赶但任何一个投影器最终都会收敛到全量事件的最新序。零漂移三条保证把前面的机制串起来零漂移由三层保证支撑架构说明见 docs/internals/overview.md术语定义见 docs/internals/glossary.md① 单事务原子性。OrchestrationEngine.ts 中事件追加、内存投影、持久化投影、命令回执写在同一个 SQL 事务内。文档原话因为持久化与投影共享事务读模型不可能与事件日志发生持久性分歧。② 每投影器游标。projection_state表的last_applied_sequence保证事件不重放、不遗漏失败时引擎会重读起始序列之后的持久化事件做对账reconcile而非猜测修补。③ 一致快照读。查询侧 Layers/ProjectionSnapshotQuery.ts 的getThreadDetailSnapshot在一个事务内同时读线程详情和snapshotSequence注释明确写道返回的序列号恰好匹配 thread 中反映的状态两次读取之间不会有投影器更新插入。客户端拿到的每个快照都能精确追溯回事件日志的某个序号——这就是可验证的零漂移。核心源码导航内存投影纯函数projector.ts持久化投影管线Layers/ProjectionPipeline.ts管线服务契约Services/ProjectionPipeline.ts快照查询服务Services/ProjectionSnapshotQuery.ts游标仓库实现Layers/ProjectionState.ts表结构定义Migrations/005_Projections.ts一句话总结T3 Code 的投影器用纯函数 单事务 每投影器游标 一致快照读四件套让读模型成为事件日志的确定性派生物——投影结果可重放、可验证、永不漂移。这也正是事件溯源模式对多端应用Web / 桌面 / 移动端最核心的工程价值。【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考