Files
knowledge-governance/internal/platform/postgres/migrations/000066_library_flow.up.sql
T
姚章浩 dc9e827656
build / build (push) Failing after 17s
feat(library): 整库版本/作业持久化与状态读取契约,生产同步默认拒绝
- 新增 library_versions:测试封存、生产生效、生产预备份三类分开登记,
  生产生效版本唯一(旧版本必须先 supersede),测试快照不能顶替生产版本
- 新增 library_jobs + library_job_stages:业务作业身份、阶段、错误与恢复说明,
  分项计数用 NULL 表示"总量未知";互斥与幂等由数据库唯一索引保证
- 新增 GET /api/v1/library/overview、/jobs、/jobs/{id};POST /syncs 闸口未齐
  返回 503 缺项且不建作业
- 封存作业落库:先建业务作业再入队,worker 推进 export 阶段并登记 test_sealed
- 发布管理读真实状态:生产未知不再顶替、差异 unknown、启动同步按缺项禁用、
  同步明细/四类分项来自持久阶段;阶段勾选只认当前作业证据
- 准备信息标注封存时间与范围,不声称实时测试库已就绪
2026-10-28 13:58:51 +08:00

57 lines
2.9 KiB
SQL

-- 整库版本与作业:把"测试封存 / 生产生效 / 生产预备份"三种版本与持久作业分开记录。
-- 现有 jobs 表是队列与租约;这里记录业务身份、阶段与结果,重启后仍可读。
CREATE TABLE library_versions (
id VARCHAR(64) PRIMARY KEY,
scope VARCHAR(16) NOT NULL CHECK (scope IN ('internal','external')),
kind VARCHAR(24) NOT NULL CHECK (kind IN ('test_sealed','production_effective','production_prebackup')),
snapshot_id VARCHAR(64) NOT NULL DEFAULT '',
version_label VARCHAR(64) NOT NULL DEFAULT '',
source_job_id VARCHAR(64) NOT NULL DEFAULT '',
evidence JSONB NOT NULL DEFAULT '{}'::jsonb,
created_by VARCHAR(128) NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL,
superseded_at TIMESTAMPTZ
);
CREATE INDEX library_versions_scope_kind ON library_versions(scope, kind, created_at DESC, id DESC);
-- 每个目标只有一个"当前生产生效版本";写入新版本时旧的必须先被 supersede。
CREATE UNIQUE INDEX library_versions_effective ON library_versions(scope)
WHERE kind = 'production_effective' AND superseded_at IS NULL;
CREATE TABLE library_jobs (
id VARCHAR(64) PRIMARY KEY,
scope VARCHAR(16) NOT NULL CHECK (scope IN ('internal','external')),
kind VARCHAR(16) NOT NULL CHECK (kind IN ('seal','sync')),
state VARCHAR(16) NOT NULL CHECK (state IN ('pending','running','succeeded','failed','cancelled')),
stage VARCHAR(32) NOT NULL DEFAULT '',
idempotency_key VARCHAR(255) NOT NULL,
request_digest VARCHAR(64) NOT NULL,
request JSONB NOT NULL DEFAULT '{}'::jsonb,
queue_job_id VARCHAR(64) NOT NULL DEFAULT '',
snapshot_id VARCHAR(64) NOT NULL DEFAULT '',
target_snapshot_id VARCHAR(64) NOT NULL DEFAULT '',
actor VARCHAR(128) NOT NULL DEFAULT '',
error TEXT NOT NULL DEFAULT '',
recovery VARCHAR(255) NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL,
finished_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX library_jobs_idempotency ON library_jobs(idempotency_key);
-- 同一目标同一类作业只能有一个在飞:互斥由数据库保证,不依赖前端或单 worker 部署。
CREATE UNIQUE INDEX library_jobs_active ON library_jobs(scope, kind)
WHERE state IN ('pending','running');
CREATE INDEX library_jobs_recent ON library_jobs(scope, created_at DESC, id DESC);
CREATE TABLE library_job_stages (
job_id VARCHAR(64) NOT NULL REFERENCES library_jobs(id) ON DELETE CASCADE,
stage VARCHAR(32) NOT NULL,
state VARCHAR(16) NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','running','succeeded','failed','skipped')),
-- NULL 表示"总量未知":绝不能当成 0,也不据此算百分比。
total BIGINT,
completed BIGINT,
bytes_total BIGINT,
bytes_done BIGINT,
detail TEXT NOT NULL DEFAULT '',
updated_at TIMESTAMPTZ NOT NULL,
PRIMARY KEY (job_id, stage)
);