init:初始化项目
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# popiartServer 薄膜持久化设计
|
||||
|
||||
这份文档描述当前的轻量化持久化方案。目标不是把 `popiartServer`
|
||||
做成第二个模型平台,而是让它只保存 PopiArt 自己的产品语义。
|
||||
|
||||
## 设计原则
|
||||
|
||||
`PopiNewAPI` 已经负责:
|
||||
|
||||
- 上游 provider key
|
||||
- 模型请求
|
||||
- 原始用量
|
||||
- 一部分任务型能力的 task 状态
|
||||
|
||||
所以 `popiartServer` 不再重复持有:
|
||||
|
||||
- 本地 artifact blob store
|
||||
- 本地 artifact metadata table
|
||||
- 本地 job_logs table
|
||||
|
||||
它只保留三类本地状态:
|
||||
|
||||
- `sessions`
|
||||
- `jobs`(更准确说是 job refs)
|
||||
- `skill_routes`
|
||||
|
||||
## 当前关系
|
||||
|
||||
```text
|
||||
session -> jobs
|
||||
jobs -> result_refs_json
|
||||
project -> skill_routes
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- `session` 保存 PopiArt 登录态和对应的 `PopiNewAPI token`
|
||||
- `jobs` 保存 skill 语义、用户归属、上游引用和同步结果引用
|
||||
- `result_refs_json` 保存同步能力的返回引用,例如 `data_url` 或远端 `url`
|
||||
- `skill_routes` 保存项目级路由覆盖
|
||||
|
||||
## 存储位置
|
||||
|
||||
默认配置来自这些环境变量:
|
||||
|
||||
- `POPIART_DATA_DIR`
|
||||
- `POPIART_SQLITE_PATH`
|
||||
- `POPIART_SESSION_SECRET`
|
||||
|
||||
默认值:
|
||||
|
||||
```text
|
||||
POPIART_DATA_DIR=./data
|
||||
POPIART_SQLITE_PATH=./data/popiart.db
|
||||
```
|
||||
|
||||
## Repository 接口
|
||||
|
||||
代码位置:
|
||||
|
||||
- `internal/server/repository.go`
|
||||
|
||||
当前只保留三层 repository:
|
||||
|
||||
1. `SessionRepository`
|
||||
2. `JobRepository`
|
||||
3. `RouteRepository`
|
||||
|
||||
没有单独的 blob storage 抽象。
|
||||
|
||||
## SQLite Schema
|
||||
|
||||
### sessions
|
||||
|
||||
```sql
|
||||
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
|
||||
|
||||
```sql
|
||||
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
|
||||
|
||||
```sql
|
||||
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)
|
||||
);
|
||||
```
|
||||
|
||||
## 运行时流程
|
||||
|
||||
### 登录
|
||||
|
||||
1. CLI 把 `PopiNewAPI token` 交给 `popiartServer`
|
||||
2. `popiartServer` 用 `/v1/models` 验证 token
|
||||
3. server 签发本地 `sess_xxx`
|
||||
4. 本地 session 持久化到 SQLite,重启后仍可继续使用
|
||||
|
||||
### 创建 job
|
||||
|
||||
1. server 解析 `skill_id -> route_key -> model_id`
|
||||
2. `jobs` 表写入一条本地 job ref
|
||||
3. goroutine 开始向 `PopiNewAPI` 发请求
|
||||
|
||||
### 完成同步结果 job
|
||||
|
||||
1. 如果 `PopiNewAPI` 直接返回同步结果,例如 `b64_json` 或 `url`
|
||||
2. `popiartServer` 只把它转换成 `result_refs_json`
|
||||
3. `GET /jobs/:id/artifacts` 时再从 `result_refs_json` 派生 artifact 列表
|
||||
|
||||
### 拉取 artifact
|
||||
|
||||
1. server 从 `artifact_id` 反推出 `job_id + result index`
|
||||
2. 读取 `jobs.result_refs_json`
|
||||
3. 如果是 `data_url`,直接解码并流式返回
|
||||
4. 如果是远端 `url`,server 代理下载并返回
|
||||
|
||||
## 当前边界
|
||||
|
||||
- server 重启后:
|
||||
- `session` 会保留
|
||||
- `job ref` 会保留
|
||||
- `artifact` 通过 `result_refs_json` 继续可读
|
||||
- 已存在的 `pending/running` job 仍然不会自动恢复执行
|
||||
- 视频类 `upstream_task` 路径只预留了字段,后续再接 `PopiNewAPI` task 查询
|
||||
- 对同步图像结果来说,`data_url` 仍然会落在 SQLite 的 `result_refs_json`
|
||||
这是当前 `PopiNewAPI` 没有统一 file id 的现实折中,但已经不再有本地 artifact 表和 blob store
|
||||
Reference in New Issue
Block a user