基于 SQLite 的 Skill 档案后端(持久化)。
用 exqlite 直连 SQLite,
把 SkillRecord 的身份/血统/计数器/历史分析全部落到单一 .db 文件:
- 跨进程重启保留:GenServer 崩溃后数据仍在
- 跨节点共享:多个 Erlang 节点可指向同一 SQLite 文件(注意:不同节点写入需自己 协调,SQLite 默认锁 wait 2s)
- 无 Ecto 依赖:轻量级、直连裸驱动,避免 schema migration 仪式
v0.3 多租户切片
v0.3 起表新增 scope 列 + 复合索引 (scope, skill_id),所有读写按 scope 过滤实现
租户隔离。skill_id 仍是表 PRIMARY KEY:依赖 cmdc 主库 CMDC.Skill.discover/1
生成的 <name>__imp_<rand_hex> skill_id 全局唯一性。不同租户即使有同名 Skill
(如 weekly_report_writer),各自的 skill_id 也不同(因随机后缀),互不冲突。
限制:如果调用方手工构造 SkillRecord 并显式指定一个跨 scope 重复的 skill_id,写入会发生
INSERT OR REPLACE冲突,覆盖另一 scope 的数据。 这种情况不推荐 —— 走CMDCSkillEngine.register_skill/2让 skill_id 由 cmdc 主库随机生成即可避免。
选项
:path— SQLite 文件路径(必填);支持:memory:运行内存数据库(测试用):pragma— 额外PRAGMA列表(默认[journal_mode: :wal, synchronous: :normal])
Schema
单张表 skill_records。复合字段(lineage / recent_analyses / tags 等)
以 JSON 字符串序列化,兼顾灵活性与可读性(可用 sqlite3 CLI 直接查询):
CREATE TABLE IF NOT EXISTS skill_records (
skill_id TEXT PRIMARY KEY,
name TEXT NOT NULL,
...
lineage TEXT NOT NULL, -- JSON
recent_analyses TEXT NOT NULL, -- JSON
...
scope TEXT NOT NULL DEFAULT 'global',
metadata TEXT NOT NULL DEFAULT '{}'
);
CREATE INDEX idx_skill_records_scope ON skill_records(scope, skill_id);用法
children = [
{CMDCSkillEngine.Store,
backend: CMDCSkillEngine.Store.Backend.SQLite,
backend_opts: [path: "./priv/skills.db"]}
]