Files
DevFlow/docs/03-模块文档/df-storage-存储层-2026-06-12.md
绝尘 998a2f243d 文档: 架构方案文档(意图识别论证+多主题愿景/论证+文档物理分类+边界清晰化)
squash合并:
- 意图识别层论证(8维度+10业界佐证)
- 多主题上下文管理愿景+并存论证+补充论证(多轮agentic)
- 架构设计文档物理分类(四子目录+INDEX+命名规范+引用同步+边界清晰化)
- 前端架构技术债清单归档
2026-06-19 15:04:04 +08:00

8.3 KiB
Raw Permalink Blame History

df-storage 存储层

创建: 2026-06-10 | 最后更新: 2026-06-15


概述

df-storage 是 DevFlow 的数据持久化层,基于 SQLite (rusqlite)负责连接管理、Schema 迁移V1-V15和 CRUD 操作。绝大多数 Repo 由 impl_repo! 宏自动生成KV 类表(app_settings)手写 Repo。


当前状态

功能 状态
SQLite 连接管理
Schema 迁移 V1-V15
impl_repo! 宏 CRUD17 Repo
KV 类手写 RepoSettingsRepo
KnowledgeRepo含向量 Sprint 15
KnowledgeEventsRepo生命线审计
事务支持 按需

数据表V1-V15 迁移历史)

版本 新增/变更
V1 ideas / projects / tasks / releases / workflow_executions / node_executions6 张基础表 + 4 索引)
V2 ideas 加 promoted_to/ai_analysis/scorestasks 加 workflow_def_id/base_branchworkflow_executions 加 project_id/task_id新建 branches 表(含 2 索引)
V3 新建 ai_conversationsarchived 列交 v4 幂等补建)
V4 幂等补列ai_conversations.archivedPRAGMA 探测,兼容坏库——历史 v3 写入版本号但 ALTER 未生效,统一交 v4 修复)
V5 幂等补列ai_conversations.prompt_tokens / completion_tokensToken 用量)
V6 幂等补列ai_conversations.models对话级多 model 记录)
V7 新建 knowledgesSprint 15
V8 幂等补列knowledges.embedding BLOBPhase 5.5 向量检索)
V9 新建 ai_providers + ai_tool_executions历史遗漏补建CREATE TABLE IF NOT EXISTS 幂等)
V10 幂等补列knowledges.reasoning新建 knowledge_events 事件表(追加型审计,支撑生命线视图,含 3 索引)
V11 幂等补列projects.deleted_at软删回收站
V12 幂等补列projects.path / projects.stack项目绑定真实代码目录 + 技术栈)
V13 新建 app_settings 表(通用应用设置 KV前端 localStorage 迁移目标)
V14 幂等补列tasks.deleted_at软删回收站对标 projects.deleted_at V11D-260616-02 决策)
V15 幂等补列tasks.review_rounds INTEGER NOT NULL DEFAULT 0review 退回累计轮数F-260616-04 任务推进链)

当前共 13 张业务表ideas / projects / tasks / releases / workflow_executions / node_executions / branches / ai_conversations / ai_providers / ai_tool_executions / knowledges / knowledge_events / app_settings。另有一张内部表 schema_version(仅记录版本号,无业务语义)。

knowledges 表V7 建表 + V8/V10 补列)

CREATE TABLE IF NOT EXISTS knowledges (
    id              TEXT PRIMARY KEY,
    kind            TEXT NOT NULL DEFAULT 'pitfall',
    title           TEXT NOT NULL,
    content         TEXT NOT NULL DEFAULT '',
    tags            TEXT,                           -- JSON array string
    status          TEXT NOT NULL DEFAULT 'candidate',
    confidence      TEXT,                           -- 'high'|'medium'|'low'
    reuse_count     INTEGER NOT NULL DEFAULT 0,
    verified        INTEGER NOT NULL DEFAULT 0,     -- 0/1
    source_project  TEXT,
    source_ref      TEXT,
    created_at      TEXT NOT NULL,                  -- 毫秒字符串
    updated_at      TEXT NOT NULL,
    reasoning       TEXT,                           -- V10 补列AI 提炼「为何值得沉淀」依据
    embedding       BLOB                            -- V8 补列f32 little-endian
);
CREATE INDEX IF NOT EXISTS idx_knowledges_status ON knowledges(status);
CREATE INDEX IF NOT EXISTS idx_knowledges_kind ON knowledges(kind);
CREATE INDEX IF NOT EXISTS idx_knowledges_reuse_count ON knowledges(reuse_count DESC);

impl_repo! 宏

自动生成以下方法:insert / get_by_id / list_all / query / update_field / update_full / delete

列名白名单ALLOWED_COLUMNS防 SQL 注入,各 Repo 声明各自允许的列。

KV 类表(app_settings 无固定 schema按 key 读写)不走 impl_repo! 宏,由手写 SettingsRepo 直接 SQL 操作。

已注册 Repo 列表12 宏生成 + 1 手写 = 13

Repo 生成方式
IdeaRepo ideas impl_repo!
ProjectRepo projects impl_repo!
TaskRepo tasks impl_repo!
ReleaseRepo releases impl_repo!
WorkflowRepo workflow_executions impl_repo!
NodeExecutionRepo node_executions impl_repo!
BranchRepo branches impl_repo!
AiProviderRepo ai_providers impl_repo!
AiConversationRepo ai_conversations impl_repo!
AiToolExecutionRepo ai_tool_executions impl_repo!
KnowledgeRepo knowledges impl_repo!+ 向量/检索自定义方法)
KnowledgeEventsRepo knowledge_events impl_repo!+ list_by_knowledge 等自定义方法)
SettingsRepo app_settings 手写KV 表不走宏)

KnowledgeRepo 自定义方法Sprint 15

方法 说明
search(query, kind?, limit) LIKE 双分支(有/无 kind 过滤),均含 WHERE status='published'ORDER BY reuse_count DESC LIMIT ?top-N≤3 用于注入
list_by_status(status) CASE WHEN confidence 语义排序High→Medium→Low用于审核收件箱
increment_reuse_count(id) UPDATE SET reuse_count = reuse_count + 1, updated_at = ?SQL 原子操作,连带刷 updated_at
top_used(limit) published 按 reuse_count DESC热门列表
set_embedding(id, &[f32]) UPDATE embedding BLOBf32 little-endian
search_vector(query_vec, limit) FR-D22026-06-14 commit 4a95f6aSELECT * 改为显式 14 列 id, kind, title, content, tags, status, confidence, reuse_count, verified, source_project, source_ref, reasoning, created_at, updated_atembedding 单独另一条 SQL 取BLOB 单独读,避免与大文本字段混取)→ 纯 Rust 余弦批量比较skip 维度不匹配。消除 SELECT * 隐式依赖,字段精简(reasoning 已在列白名单中)
list_non_archived() WHERE status != 'archived' 全量CASE confidence 语义排序high>medium>low次 created_at DESC → Vec<KnowledgeRecord>

向量工具函数

fn f32s_to_blob(v: &[f32]) -> Vec<u8>        // f32 → little-endian bytes
fn blob_to_f32s(b: &[u8]) -> Vec<f32>        // bytes → f32chunks_exact(4),尾部非 4 倍数残字节截断丢弃)
fn cosine_similarity(a: &[f32], b: &[f32]) -> f32   // 点积 / (‖a‖‖b‖ + 1e-8 防零除),零向量返回有限值

不引入 sqlite-vec:规避 Windows MSVC 下编译 C 扩展的风险。纯 Rust 实现,零外部 C 依赖。


迁移幂等设计

迁移机制:schema_version 表记录已应用版本,run() 读出 MAX(version)current_version,按 current_version < N 顺序应用 V1…V15每版应用后 INSERT 对应版本号)。当前最新目标版本为 15

注:早期版本曾用 MIGRATION_VERSION 常量,现已无此常量——版本号直接散落在各 if current_version < N 分支,由 schema_version 表动态跟踪。

v4 解法PRAGMA 探测列存在性

关键列补建不依赖版本号,用 PRAGMA table_info(<table>) 探测实际 schema缺列才 ALTER TABLE ADD COLUMN

  • 对新库列已由建表带入、老库DDL 正常生效)、坏库(版本号已写入但 DDL 漏生效)三种情况都安全幂等。
  • V4/V5/V6/V8/V10/V11/V12/V14/V15 均复用此模式(补列迁移)。
  • V9/V10/V13 用 CREATE TABLE IF NOT EXISTS 幂等建表(老库已有表则跳过)。

文件结构

crates/df-storage/src/
├── lib.rs          — 模块入口,导出公共 API
├── db.rs           — SQLite 连接管理Database struct
├── migrations.rs   — V1-V15 迁移逻辑schema_version 表跟踪版本)
├── models.rs       — 全部 *Record struct含 KnowledgeRecord / KnowledgeEventRecord
└── crud.rs         — impl_repo! 宏 + 全部 Repo含 KnowledgeRepo / KnowledgeEventsRepo / SettingsRepo

相关文档