feat: add application productivity foundations
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 11:13:03 +05:30
parent 46195462c3
commit 64ab20cc95
42 changed files with 1533 additions and 40 deletions
+158
View File
@@ -0,0 +1,158 @@
import type { Db } from "@wrnexus/db";
import type { Job } from "./index.ts";
import type { QueueJobRecord, QueueStore } from "./durable.ts";
const SAFE = /^[A-Za-z_][A-Za-z0-9_]*$/;
const check = (value: string) => {
if (!SAFE.test(value)) throw new TypeError(`Invalid queue table: ${value}`);
return value;
};
export async function installDatabaseQueueSchema(db: Db, table = "wrnexus_jobs") {
const target = check(table);
await db.exec(`CREATE TABLE IF NOT EXISTS ${target} (
id VARCHAR(191) PRIMARY KEY, name VARCHAR(191) NOT NULL, payload TEXT NOT NULL,
run_at BIGINT NOT NULL, priority INTEGER NOT NULL DEFAULT 0,
idempotency_key VARCHAR(191), lease_owner VARCHAR(191), lease_until BIGINT
)`);
await db.exec(`CREATE TABLE IF NOT EXISTS ${target}_history (
id VARCHAR(191) PRIMARY KEY, name VARCHAR(191) NOT NULL, state VARCHAR(32) NOT NULL,
payload TEXT NOT NULL, error TEXT, finished_at BIGINT NOT NULL
)`);
for (const statement of [
`CREATE INDEX ${target}_due ON ${target} (run_at, priority)`,
`CREATE UNIQUE INDEX ${target}_idempotency ON ${target} (name, idempotency_key)`,
]) {
try {
await db.exec(statement);
} catch (error) {
if (!/exist|duplicate|already/i.test(String(error))) throw error;
}
}
}
export function databaseQueueStore(db: Db, table = "wrnexus_jobs"): QueueStore {
const target = check(table);
type Row = { payload: string };
const decode = (row: Row) => JSON.parse(row.payload) as Job;
return {
async put(job) {
if (db.driver.dialect === "mysql") {
await db.exec(
`INSERT INTO ${target} (id,name,payload,run_at,priority,idempotency_key,lease_owner,lease_until)
VALUES (?,?,?,?,?,?,NULL,NULL) ON DUPLICATE KEY UPDATE name=VALUES(name),payload=VALUES(payload),run_at=VALUES(run_at),priority=VALUES(priority),lease_owner=NULL,lease_until=NULL`,
[
job.id,
job.name,
JSON.stringify(job),
job.runAt,
job.priority,
job.idempotencyKey ?? null,
],
);
} else {
await db.exec(
`INSERT INTO ${target} (id,name,payload,run_at,priority,idempotency_key,lease_owner,lease_until)
VALUES (?,?,?,?,?,?,NULL,NULL) ON CONFLICT(id) DO UPDATE SET name=excluded.name,payload=excluded.payload,run_at=excluded.run_at,priority=excluded.priority,lease_owner=NULL,lease_until=NULL`,
[
job.id,
job.name,
JSON.stringify(job),
job.runAt,
job.priority,
job.idempotencyKey ?? null,
],
);
}
},
async get(id) {
const row = await db.one<Row>(`SELECT payload FROM ${target} WHERE id = ?`, [id]);
return row ? decode(row) : null;
},
async remove(id) {
await db.exec(`DELETE FROM ${target} WHERE id = ?`, [id]);
},
async due(now, limit) {
return (
await db.all<Row>(
`SELECT payload FROM ${target} WHERE run_at <= ? AND (lease_until IS NULL OR lease_until < ?) ORDER BY priority DESC,run_at LIMIT ?`,
[now, now, limit],
)
).map(decode);
},
async list(name) {
return (
await db.all<Row>(
`SELECT payload FROM ${target}${name ? " WHERE name = ?" : ""} ORDER BY run_at`,
name ? [name] : [],
)
).map(decode);
},
async findByIdempotencyKey(name, key) {
const row = await db.one<Row>(
`SELECT payload FROM ${target} WHERE name = ? AND idempotency_key = ?`,
[name, key],
);
return row ? decode(row) : null;
},
async size() {
return Number(
(await db.one<{ total: number | string }>(`SELECT COUNT(*) AS total FROM ${target}`))
?.total ?? 0,
);
},
async claim(id, worker, leaseUntil, now = Date.now()) {
return (
(
await db.exec(
`UPDATE ${target} SET lease_owner=?,lease_until=? WHERE id=? AND (lease_until IS NULL OR lease_until < ?)`,
[worker, leaseUntil, id, now],
)
).changes > 0
);
},
async release(id, worker) {
await db.exec(
`UPDATE ${target} SET lease_owner=NULL,lease_until=NULL WHERE id=? AND lease_owner=?`,
[id, worker],
);
},
async archive(record) {
const values = [
record.job.id,
record.job.name,
record.state,
JSON.stringify(record.job),
record.error ?? null,
record.finishedAt,
];
if (db.driver.dialect === "mysql")
await db.exec(
`INSERT INTO ${target}_history (id,name,state,payload,error,finished_at) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE state=VALUES(state),payload=VALUES(payload),error=VALUES(error),finished_at=VALUES(finished_at)`,
values,
);
else
await db.exec(
`INSERT INTO ${target}_history (id,name,state,payload,error,finished_at) VALUES (?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET state=excluded.state,payload=excluded.payload,error=excluded.error,finished_at=excluded.finished_at`,
values,
);
},
async history(id) {
const rows = await db.all<{
state: QueueJobRecord["state"];
payload: string;
error: string | null;
finished_at: number;
}>(
`SELECT state,payload,error,finished_at FROM ${target}_history${id ? " WHERE id = ?" : ""} ORDER BY finished_at DESC`,
id ? [id] : [],
);
return rows.map((row) => ({
job: JSON.parse(row.payload),
state: row.state,
error: row.error ?? undefined,
finishedAt: Number(row.finished_at),
}));
},
};
}