feat(db): 0013 tasks tables and 0014 agent_run_event; tasks uses db migrations

tasks_run_meta/tasks_fact/tasks_op_ledger move into packages/db (if not exists, old
tasks_migration tables dropped); packages/tasks/migrations and migrateTasksTables
removed, tests migrate their schema with @umt/db. agent_run_event(run_id, seq, type,
at, payload) with (run_id, seq) primary key; types regenerated, db-sync covers it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 19:15:50 +08:00
1 parent db5352eecd
commit da8e53bbca
13 files changed
+250 -36

No files matched your search

+16 -8
View File
@@ -1,7 +1,15 @@
import { sql } from "kysely";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { FencingError, getOperation, migrateTasksTables, withAttemptToken } from "../src/index.ts";
import { connectDb, dropSchemas, pgAvailable, resetSchemas, type TestDb, testSchemas } from "./helpers.ts";
import { FencingError, getOperation, withAttemptToken } from "../src/index.ts";
import {
connectDb,
dropSchemas,
migrateBizSchema,
pgAvailable,
resetSchemas,
type TestDb,
testSchemas,
} from "./helpers.ts";
const schemas = testSchemas("ledger");
const hasPg = await pgAvailable();
@@ -12,8 +20,8 @@ describe.skipIf(!hasPg)("withAttemptToken(操作账本 fencing)", () => {
beforeAll(async () => {
await resetSchemas(schemas);
db = connectDb(schemas.biz);
await migrateTasksTables(db);
await sql`CREATE TABLE download_task (id text PRIMARY KEY, hash text)`.execute(db);
await migrateBizSchema(db, schemas.biz);
await sql`CREATE TABLE ledger_probe (id text PRIMARY KEY, hash text)`.execute(db);
});
afterAll(async () => {
@@ -34,7 +42,7 @@ describe.skipIf(!hasPg)("withAttemptToken(操作账本 fencing)", () => {
{
runId: "r1",
commit: async (trx, result) => {
await sql`INSERT INTO download_task (id, hash) VALUES ('d1', ${result.hash})`.execute(trx);
await sql`INSERT INTO ledger_probe (id, hash) VALUES ('d1', ${result.hash})`.execute(trx);
},
},
);
@@ -65,7 +73,7 @@ describe.skipIf(!hasPg)("withAttemptToken(操作账本 fencing)", () => {
return "old";
},
{
commit: async (trx) => void (await sql`INSERT INTO download_task (id, hash) VALUES ('d2', 'old')`.execute(trx)),
commit: async (trx) => void (await sql`INSERT INTO ledger_probe (id, hash) VALUES ('d2', 'old')`.execute(trx)),
},
);
await oldStartedP;
@@ -80,7 +88,7 @@ describe.skipIf(!hasPg)("withAttemptToken(操作账本 fencing)", () => {
return "new";
},
{
commit: async (trx) => void (await sql`INSERT INTO download_task (id, hash) VALUES ('d2', 'new')`.execute(trx)),
commit: async (trx) => void (await sql`INSERT INTO ledger_probe (id, hash) VALUES ('d2', 'new')`.execute(trx)),
},
);
expect(fresh).toBe("new");
@@ -88,7 +96,7 @@ describe.skipIf(!hasPg)("withAttemptToken(操作账本 fencing)", () => {
releaseOld();
await expect(oldAttempt).rejects.toBeInstanceOf(FencingError);
const r = await sql<{ hash: string }>`SELECT hash FROM download_task WHERE id = 'd2'`.execute(db);
const r = await sql<{ hash: string }>`SELECT hash FROM ledger_probe WHERE id = 'd2'`.execute(db);
expect(r.rows).toEqual([{ hash: "new" }]);
expect(await getOperation(db, "op-2")).toMatchObject({ status: "succeeded", attempts: 2, result: "new" });
});