feat(system): retention cleanup jobs, storage panel API and health storage level (CACHE-2)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d13c18b4b1
commit
05b163ce32
9 files changed
+1254
-9
No files matched your search
@@ -0,0 +1,79 @@
|
||||
import type { Kysely } from "kysely";
|
||||
import { execDdl } from "../src/migration-helpers.ts";
|
||||
|
||||
// CACHE-2 存储保留(docs/runbook/storage.md):
|
||||
// - 保留清理按时间列分批删除,给还没有时间索引的高流水表补上(已有:task_created_idx、agent_run_event_at_idx、
|
||||
// process_heartbeat_sample_at_idx);
|
||||
// - 按表设置 autovacuum:批量删除 / 追加为主的大表降低触发比例,频繁原地更新的小表更激进,避免死元组堆积。
|
||||
// 引擎 schema(openworkflow)的表由引擎自己建,这里不动。
|
||||
|
||||
const INDEXES: [name: string, ddl: string][] = [
|
||||
["observation_created_idx", "observation (created_at)"],
|
||||
["sse_event_at_idx", "sse_event (at)"],
|
||||
["audit_event_at_idx", "audit_event (at)"],
|
||||
["capability_invocation_created_idx", "capability_invocation (created_at)"],
|
||||
["agent_run_message_created_idx", "agent_run_message (created_at)"],
|
||||
["tasks_fact_created_idx", "tasks_fact (created_at)"],
|
||||
["tasks_run_meta_created_idx", "tasks_run_meta (created_at)"],
|
||||
["tasks_op_ledger_started_idx", "tasks_op_ledger (started_at) where status = 'succeeded'"],
|
||||
];
|
||||
|
||||
/** 追加 + 批量删除为主的大表 */
|
||||
const APPEND_TABLES = [
|
||||
"observation",
|
||||
"sse_event",
|
||||
"audit_event",
|
||||
"agent_run_event",
|
||||
"process_heartbeat_sample",
|
||||
"capability_invocation",
|
||||
"task",
|
||||
"tasks_fact",
|
||||
"tasks_run_meta",
|
||||
];
|
||||
const APPEND_OPTS = {
|
||||
autovacuum_vacuum_scale_factor: "0.05",
|
||||
autovacuum_analyze_scale_factor: "0.02",
|
||||
autovacuum_vacuum_insert_scale_factor: "0.1",
|
||||
};
|
||||
|
||||
/** 频繁原地更新的小表(心跳 15 秒一次、令牌桶、调度状态、缓存命中刷新 accessed_at) */
|
||||
const HOT_TABLES = ["process_heartbeat", "rate_limit_bucket", "scheduled_job", "kv_cache", "outbox_event"];
|
||||
const HOT_OPTS = {
|
||||
autovacuum_vacuum_scale_factor: "0.02",
|
||||
autovacuum_vacuum_threshold: "100",
|
||||
autovacuum_analyze_scale_factor: "0.05",
|
||||
};
|
||||
|
||||
const setOpts = (tables: string[], o: Record<string, string>) =>
|
||||
tables
|
||||
.map(
|
||||
(t) =>
|
||||
`alter table ${t} set (${Object.entries(o)
|
||||
.map(([k, v]) => `${k} = ${v}`)
|
||||
.join(", ")});`,
|
||||
)
|
||||
.join("\n");
|
||||
const resetOpts = (tables: string[], o: Record<string, string>) =>
|
||||
tables.map((t) => `alter table ${t} reset (${Object.keys(o).join(", ")});`).join("\n");
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(
|
||||
db,
|
||||
`${INDEXES.map(([n, d]) => `create index if not exists ${n} on ${d};`).join("\n")}
|
||||
${setOpts(APPEND_TABLES, APPEND_OPTS)}
|
||||
${setOpts(HOT_TABLES, HOT_OPTS)}
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 同上
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(
|
||||
db,
|
||||
`${resetOpts(HOT_TABLES, HOT_OPTS)}
|
||||
${resetOpts(APPEND_TABLES, APPEND_OPTS)}
|
||||
${INDEXES.map(([n]) => `drop index if exists ${n};`).join("\n")}
|
||||
`,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user