import type { Kysely } from "kysely"; import { dropTables, execDdl, oneOf } from "../src/migration-helpers.ts"; // W7-C 定时任务统一注册表(docs/runbook/schedules.md): // - scheduled_job:稳定 key 为主键(如 feeds.poll);模块启动时登记默认值(customized 后不覆盖 enabled/schedule); // io worker 上持有咨询锁的调度器按 next_run_at / run_requested_at 触发,结果写回 last_* 与计数。 // kind=agent_check 为 Agent 巡检(config 存目标模板/能力白名单/预算/触发条件),builtin=false 为用户自定义。 // - scheduled_job_run:运行历史,每个任务只保留最近若干条(调度器写入时裁剪);巡检入队的 agent_run 结束后 // 调度器回填 agent_status 与 summary。 const GROUPS = ["collect", "download", "organize", "maintain", "agent"] as const; const KINDS = ["task", "agent_check"] as const; const STATUSES = ["ok", "failed", "skipped", "running"] as const; const TRIGGERS = ["schedule", "manual", "skip"] as const; // biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型 export async function up(db: Kysely): Promise { await execDdl( db, ` create table scheduled_job ( id text primary key, name text not null, description text, board_group text not null ${oneOf("board_group", GROUPS)}, kind text not null ${oneOf("kind", KINDS)}, builtin boolean not null default true, available boolean not null default true, enabled boolean not null, default_enabled boolean not null, schedule jsonb not null, default_schedule jsonb not null, customized boolean not null default false, config jsonb not null default '{}'::jsonb, last_run_at timestamptz, last_status text ${oneOf("last_status", STATUSES)}, last_duration_ms integer, last_error text, next_run_at timestamptz, run_requested_at timestamptz, running_since timestamptz, run_count integer not null default 0, fail_count integer not null default 0, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create trigger scheduled_job_touch_updated_at before update on scheduled_job for each row execute function umt_touch_updated_at(); create index scheduled_job_due_idx on scheduled_job (next_run_at) where enabled; create table scheduled_job_run ( id uuid primary key default gen_random_uuid(), job_id text not null references scheduled_job (id) on delete cascade, trigger text not null ${oneOf("trigger", TRIGGERS)}, status text not null ${oneOf("status", STATUSES)}, started_at timestamptz not null default now(), finished_at timestamptz, duration_ms integer, error text, summary text, agent_run_id uuid references agent_run (id) on delete set null, agent_status text, created_at timestamptz not null default now() ); create index scheduled_job_run_job_idx on scheduled_job_run (job_id, started_at desc); `, ); } // biome-ignore lint/suspicious/noExplicitAny: 同上 export async function down(db: Kysely): Promise { await execDdl(db, dropTables(["scheduled_job_run", "scheduled_job"])); }