Files
qinglong/docs/adr/ADR-0292-local-sqlite-run-persistence-support-module.md

7.3 KiB
Raw Permalink Blame History

ADR-0292Local SQLite Run Persistence Support 内部模块

  • 状态:Accepted
  • 日期:2026-08-09
  • 关联:D-85、D-87、D-213、D-257、ADR-0007、ADR-0069、ADR-0280、ADR-0290、ADR-0291

上下文

ADR-0291 已把具名 LocalSqliteRunReader 移到独立文件,但 runRepository.ts 仍同时持有 Run/Attempt/Event/Retry 列声明、SELECT/INSERT/UPDATE SQL builder、row codec、SQLite driver error mapping、有界 query helper、Transaction、 Security/Secret 映射和产品 Facade。Reader 为避免复制,通过一个冻结 support 对象从 Facade 文件接收这些函数;这只是 安全的过渡边界,并没有消除反向依赖。

强制完整 GitNexus 索引表明五个 scalar/JSON codec 为 CRITICAL,最大 13 direct/88 total、2 processes/7 modules mapSqliteErrorqueryRowssingleRow 和 SQLite code/number 解码为 HIGH,最大 17 direct/46 total、1 process/ 4 modules。Facade 仍为 CRITICAL30 direct/63 total),Reader 为 HIGH15/40),Transaction 为 HIGH15/37)。 因此本批次必须是逐字语义保留的模块抽取,不能同时泛化不同领域的 SQLite codec。

决策

  1. 在既有 @qinglong/local-sqlite/src/run/ 下新增 package-private runPersistence.ts,集中:
    • Run/Attempt/Event/Retry column metadata 和 SELECT/INSERT/UPDATE SQL 常量;
    • write value normalization、row scalar/JSON/enum/blob/boolean codec 与 Run record 映射;
    • SQLite error code/number/message 分类、mapSqliteError、event payload 上限;
    • queryRows 和 duplicate-identity singleRow
  2. 所有被迁移函数体、错误类型、错误文本、NULL/undefined/empty-string 处理、JSON parsing、enum 集合、column 顺序、 SQL 文本和 payload byte 计算逐字保持。不得借重构修改协议或“统一”错误。
  3. LocalSqliteRunReader 直接导入 persistence support,不再接收函数对象;构造器恢复只接收同一 DatabaseSyncLocalSqliteRunTransaction 继续继承 ReaderFacade 继续通过唯一 LocalSqliteOperationAuthority 调度两者。
  4. LocalSqliteRunRepository、Transaction 和现有 Security/Secret 映射只改为 import 同一 support。公开构造器、 runtime-core ports、root/subpath exports、事务边界、close/error mapping 和消费者不变。
  5. 新模块不得从 package.json#exportsindex.tsruntime.ts 导出,也不得创建 connection、transaction、queue、 timer、watcher、cache、listener 或后台工作。
  6. Completion Receipt、Task Definition、Owner、Tool 等模块的相似 helper 具有不同 empty/null/error 语义,本批次不合并; 后续只有在先冻结共同 contract 后才可共享,不能按函数名相同机械去重。
  7. 不新增 workspace package、生产 dependency、migration、表、索引、进程或部署单元;19-package ledger 与 Edge/ Standalone 制品和 RSS 上限保持不变。

被拒绝的方案

  • 建立 package-wide 万能 row codec:不同领域对空字符串、NULL、错误类型和错误文本要求不同,会造成静默语义漂移。
  • 继续由 Facade 向 Reader 注入函数对象:可以运行,但让只读模块的基础依赖反向由产品 Facade 组装,长期难以演进。
  • 复制 support 到 Reader/Transaction:会复制列顺序、SQL projection 和 normalization,读写路径可能分叉。
  • 把 support 拆成新 workspace package:没有独立部署、权限、依赖或消费者 closure,只增加低配设备 importer/SBOM。
  • 同时移动 Transaction 或 Security/Secret authority:会把机械 support 抽取扩大为事务 ownership 重构,无法归因回归。

接受条件

  1. 原 support 函数和常量只存在于 runPersistence.tsReader/Fascade/Transaction 没有复制;源码与错误文本保持等价。
  2. Reader 恢复单参数构造,Transaction 写方法与 Facade BEGIN/COMMIT/ROLLBACK、enqueue/close 完全不变。
  3. Run、startup recovery、dispatch/control、Security Audit、Project Policy、Local Secret 和 corruption/error 定向测试通过; Local SQLite 全量零回归。
  4. 完整 19-package clean build/test、backend、六项架构/部署审计及十档 artifact/RSS 门通过;package 仍为 19 个、 singleSourcePackages=[],公开 exports、依赖与 migration chain 不变。
  5. 强制完整 GitNexus 索引后重查全部 CRITICAL/HIGH helper、Facade/Reader/Transaction 和执行流,再运行 detect_changes all/compare develop。如果 support 丢失可索引性、生产流程扩散或风险上升,ADR 不得 Accepted。

接受证据

  • runPersistence.ts 为 551 行,成为 Run 子域唯一的 column/SQL/codec/error/query supportrunRepository.ts 从 1,990 行降至 1,457 行,runReader.ts 从 762 行降至 667 行。Reader 恢复只接收同一 DatabaseSync,旧 LocalSqliteRunReaderSupport 注入对象已删除;Transaction 写方法、BEGIN/COMMIT/ROLLBACK、Facade enqueue/close、 runtime-core port 和 package exports 均未改变。
  • 跨 Run/Startup/Dispatch/Control/Execution Revision/Security Audit/Policy/Secret 的定向回归 74/74、Local SQLite 192/192、完整 19-package clean build/test 与 backend 1,1101,108 pass/2 skip)通过;cluster dependency、package boundary、Edge import、cluster deployment、CloudNativePG 与 local image 六项审计均 compatible:true
  • workspace 保持 19 个 package、765 个 source、49 个受审根入口和 716 个领域内嵌套实现, singleSourcePackages=[]Local SQLite 为 153/3/150。没有新增生产 dependency、migration、表、索引、进程、 部署单元或公开 specifier。
  • 十档制品/RSS 门全部 compatible。最小 Edge 为 3,623,406 bytes/329 files/45 loaded modulesRSS delta 11,599,872 bytes;最大 Standalone Application AI 为 6,111,027 bytes/488 files/101 loaded modulesRSS delta 21,250,048 bytes,均低于硬上限。
  • 强制完整索引为 43,173 nodes/98,227 edges/1,693 clusters/265 flows。五个既有 scalar/JSON helper 仍为 CRITICAL 最大 requiredString 17 direct/108 total、requiredInteger 19/107mapSqliteErrorqueryRows 和 SQLite code/number decoder 仍为 HIGH,最大 20/70singleRow 为 MEDIUM13/42)。直接调用数比 support-object 基线更 完整,是删除间接注入后图谱恢复可见性,不是新消费者或执行流;其风险等级没有升级。Facade 为 CRITICAL30/64)、 Reader 为 HIGH15/40)、Transaction 为 HIGH15/38),全部仍为 0 affected process;其余 persistence helper 最高 MEDIUM。
  • 本批次只改变 Local SQLite package 内源码组织,未触及 PostgreSQL、Cluster、migration 或 HA 状态,因此不重复执行 与变更无关的物理 PostgreSQL HA;对应结构、依赖和部署审计已覆盖其不变性。
  • detect_changes all/compare develop 分别为 12 files/31 symbols 与 14/34,均为 low/0 affected processQL3 孵化树大部分仍 untracked,因此该结果只作为逐符号 impact、完整测试、审计与制品门的补充证据。

后续边界

  • Security/Secret authority 仍在 Run Facade 内是下一项真实职责问题,但必须先按共同授权事实和事务围栏建模。
  • 其他领域的重复 scalar helper 只能按明确 contract 分组迁移,不能把本 ADR 当成全 package 泛化授权。