feat: cap job_runs history at last 10 per job
Tailscale, Patchmon, and Semaphore sync jobs all wrote into a shared job_runs table with no retention. With default poll intervals of 15-60 minutes, history grew unbounded. - Add pruneJobRuns(jobId) and pruneAllJobRuns() helpers. - Prune after every completeJobRun() so new runs trim old ones. - Prune once on init() to clean up existing over-cap rows. - Prune in importJobs() so re-imported runs are also capped. - Defensive LIMIT 10 in getJobRuns() for the read path. No UI changes needed — _renderRunList already renders whatever the server returns. No schema migration — only row deletions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-2
@@ -6,6 +6,8 @@ import { fileURLToPath } from 'url';
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const DEFAULT_PATH = join(__dirname, '../data/catalyst.db');
|
||||
|
||||
const JOB_RUN_LIMIT = 10;
|
||||
|
||||
let db;
|
||||
|
||||
function init(path) {
|
||||
@@ -17,7 +19,7 @@ function init(path) {
|
||||
db.exec('PRAGMA foreign_keys = ON');
|
||||
db.exec('PRAGMA synchronous = NORMAL');
|
||||
createSchema();
|
||||
if (path !== ':memory:') { seed(); seedJobs(); }
|
||||
if (path !== ':memory:') { seed(); seedJobs(); pruneAllJobRuns(); }
|
||||
}
|
||||
|
||||
function createSchema() {
|
||||
@@ -267,6 +269,7 @@ export function importJobs(jobRows, jobRunRows = []) {
|
||||
`);
|
||||
for (const r of jobRunRows) insertRun.run(r);
|
||||
}
|
||||
pruneAllJobRuns();
|
||||
db.exec('COMMIT');
|
||||
}
|
||||
|
||||
@@ -326,10 +329,28 @@ export function completeJobRun(runId, status, result) {
|
||||
db.prepare(`
|
||||
UPDATE job_runs SET ended_at=strftime('%Y-%m-%dT%H:%M:%f', 'now'), status=@status, result=@result WHERE id=@id
|
||||
`).run({ id: runId, status, result });
|
||||
const row = db.prepare('SELECT job_id FROM job_runs WHERE id = ?').get(runId);
|
||||
if (row) pruneJobRuns(row.job_id);
|
||||
}
|
||||
|
||||
export function getJobRuns(jobId) {
|
||||
return db.prepare('SELECT * FROM job_runs WHERE job_id = ? ORDER BY id DESC').all(jobId);
|
||||
return db.prepare(`SELECT * FROM job_runs WHERE job_id = ? ORDER BY id DESC LIMIT ${JOB_RUN_LIMIT}`).all(jobId);
|
||||
}
|
||||
|
||||
function pruneJobRuns(jobId) {
|
||||
db.prepare(`
|
||||
DELETE FROM job_runs
|
||||
WHERE job_id = ?
|
||||
AND id NOT IN (
|
||||
SELECT id FROM job_runs WHERE job_id = ? ORDER BY id DESC LIMIT ?
|
||||
)
|
||||
`).run(jobId, jobId, JOB_RUN_LIMIT);
|
||||
}
|
||||
|
||||
function pruneAllJobRuns() {
|
||||
for (const j of db.prepare('SELECT id FROM jobs').all()) {
|
||||
pruneJobRuns(j.id);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Test helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user