You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.4 KiB
4.4 KiB
popiartServer 薄膜持久化设计
这份文档描述当前的轻量化持久化方案。目标不是把 popiartServer
做成第二个模型平台,而是让它只保存 PopiArt 自己的产品语义。
设计原则
PopiNewAPI 已经负责:
- 上游 provider key
- 模型请求
- 原始用量
- 一部分任务型能力的 task 状态
所以 popiartServer 不再重复持有:
- 本地 artifact metadata table
- 本地 job_logs table
它只保留三类本地状态:
sessionsjobs(更准确说是 job refs)skill_routesmedia blobs + metadata
当前关系
session -> jobs
jobs -> result_refs_json
project -> skill_routes
media -> local files + metadata json
其中:
session保存 PopiArt 登录态和对应的PopiNewAPI tokenjobs保存 skill 语义、用户归属、上游引用和同步结果引用result_refs_json保存同步能力的结果引用;新结果会优先 re-host 到本地 media storeskill_routes保存项目级路由覆盖media保存稳定 URL 所需的本地文件与元数据
存储位置
默认配置来自这些环境变量:
POPIART_DATA_DIRPOPIART_SQLITE_PATHPOPIART_SESSION_SECRET
默认值:
POPIART_DATA_DIR=./data
POPIART_SQLITE_PATH=./data/popiart.db
Repository 接口
代码位置:
internal/server/repository.go
当前只保留三层 repository:
SessionRepositoryJobRepositoryRouteRepository
本地开发版没有对象存储依赖,但现在有一个轻量 media 存储层:
- blob 文件保存在
POPIART_DATA_DIR/media/blobs/ - metadata JSON 保存在
POPIART_DATA_DIR/media/meta/
SQLite Schema
sessions
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
user_json TEXT NOT NULL,
token_enc BLOB NOT NULL,
token_masked TEXT NOT NULL,
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL
);
jobs
CREATE TABLE jobs (
job_id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
session_id TEXT,
project_id TEXT,
skill_id TEXT,
route_key TEXT,
model_id TEXT,
exec_mode TEXT NOT NULL,
newapi_task_id TEXT,
status TEXT NOT NULL,
input_json TEXT NOT NULL,
result_refs_json TEXT,
usage_json TEXT,
error_json TEXT,
idempotency_key TEXT,
created_at TEXT NOT NULL,
started_at TEXT,
finished_at TEXT,
UNIQUE(user_id, idempotency_key)
);
skill_routes
CREATE TABLE skill_routes (
route_key TEXT NOT NULL,
scope_key TEXT NOT NULL,
model_id TEXT NOT NULL,
options_json TEXT,
updated_at TEXT NOT NULL,
PRIMARY KEY(route_key, scope_key)
);
运行时流程
登录
- CLI 把
PopiNewAPI token交给popiartServer popiartServer用/v1/models验证 token- server 签发本地
sess_xxx - 本地 session 持久化到 SQLite,重启后仍可继续使用
创建 job
- server 解析
skill_id -> route_key -> model_id jobs表写入一条本地 job ref- goroutine 开始向
PopiNewAPI发请求
完成同步结果 job
- 如果
PopiNewAPI直接返回同步结果,例如b64_json或url popiartServer会先把结果 re-host 到本地 media store- 再把本地
local_path + media_id + stable url写进result_refs_json GET /jobs/:id/artifacts时再从result_refs_json派生 artifact 列表
拉取 artifact
- server 从
artifact_id反推出job_id + result index - 读取
jobs.result_refs_json - 如果是本地
local_path,直接读取本地文件并流式返回 - 如果是旧的
data_url,直接解码并流式返回 - 如果是旧的远端
url,server 代理下载并返回
读取 media
POST /v1/media/upload会把本地文件写入media/blobs/- server 同时写一份 metadata JSON 到
media/meta/ GET /v1/media/:id返回 media 元数据GET /v1/media/:id/content返回可供模型或客户端直接 fetch 的稳定内容路径
当前边界
- server 重启后:
session会保留job ref会保留artifact通过result_refs_json继续可读- 新
media文件和 metadata 会继续可读
- 已存在的
pending/runningjob 仍然不会自动恢复执行 - 视频类
upstream_task路径只预留了字段,后续再接PopiNewAPItask 查询 - 旧数据里仍可能存在
data_url或上游url - 新写入路径优先落本地 media store,从而给 artifact 补出稳定
url