CMDCSkillEngine.Store (cmdc_skill_engine v0.2.2)

Copy Markdown View Source

Skill 档案存储 —— 可插拔后端 + 串行化写入的 GenServer。

自 v0.2 起 Store 不再直接操作 ETS,而是把存储细节委托给 CMDCSkillEngine.Store.Backend。默认后端仍是 ETS(零依赖、适合开发/单元测试), 需要跨重启持久化时可切到 SQLite:

# ETS(默认)
children = [CMDCSkillEngine.Store]

# SQLite
children = [
  {CMDCSkillEngine.Store,
    backend: CMDCSkillEngine.Store.Backend.SQLite,
    backend_opts: [path: "./priv/skills.db"]}
]

责任

  • SkillRecord 的 CRUD
  • 版本 DAG 查询(按 lineage.parent_skill_ids 追溯)
  • 原子计数器(selections / applied / completions / fallbacks)
  • 版本血统 DAG 的本地图遍历(跨后端共用逻辑)

并发语义

  • 所有写入通过 GenServer 串行化,保证原子性
  • 读取(get_record / list_active / get_version_chain)与写入同走 GenServer, 避免 backend 内部的并发一致性问题;后端实现可以假设任意时刻只有一个 handle_call 在执行

Summary

Functions

返回当前挂载的 backend 模块与状态(调试/运维用)。

Returns a specification to start this module under a supervisor.

按 skill_id 取回档案。

批量取回档案,返回只含存在 id 的 map。

返回某个 Skill 的完整版本链:根节点在最前,按 generation 升序。

返回所有 is_active = true 的 SkillRecord,按 name 升序。

清空所有档案(测试专用)。

插入/覆盖一条 SkillRecord。

启动 Store GenServer。

原子递增计数器。支持 :selections / :applied / :completions / :fallbacks

Functions

backend_info()

@spec backend_info() :: {module(), term()}

返回当前挂载的 backend 模块与状态(调试/运维用)。

注意:backend_state 可能包含底层 handle(例如 SQLite conn), 调用方不应直接操作。

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

get_record(skill_id)

@spec get_record(String.t()) ::
  {:ok, CMDCSkillEngine.Types.SkillRecord.t()} | {:error, :not_found}

按 skill_id 取回档案。

get_records(skill_ids)

@spec get_records([String.t()]) ::
  {:ok, %{required(String.t()) => CMDCSkillEngine.Types.SkillRecord.t()}}

批量取回档案,返回只含存在 id 的 map。

get_version_chain(skill_id)

@spec get_version_chain(String.t()) :: {:ok, [CMDCSkillEngine.Types.SkillRecord.t()]}

返回某个 Skill 的完整版本链:根节点在最前,按 generation 升序。

从传入 skill_id 回溯到所有祖先节点。如果中间缺链,返回能重建的 最长前缀(遇到第一个缺失祖先即停止向上追溯,保证返回顺序稳定)。

list_active()

@spec list_active() :: {:ok, [CMDCSkillEngine.Types.SkillRecord.t()]}

返回所有 is_active = true 的 SkillRecord,按 name 升序。

reset()

@spec reset() :: :ok

清空所有档案(测试专用)。

save_record(record)

插入/覆盖一条 SkillRecord。

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

启动 Store GenServer。

选项

update_counters(skill_id, increments)

@spec update_counters(
  String.t(),
  keyword()
) :: :ok | {:error, :not_found}

原子递增计数器。支持 :selections / :applied / :completions / :fallbacks

CMDCSkillEngine.Store.update_counters("sk_123", selections: 1, applied: 1)