diff --git a/src/history.test.ts b/src/history.test.ts new file mode 100644 index 0000000..bb2741e --- /dev/null +++ b/src/history.test.ts @@ -0,0 +1,26 @@ +import { expect, test } from "bun:test"; + +import { cleanUp, getCount, insertJobHistory, init, truncate } from "./history"; + +init("test.sqlite"); +truncate(); + +test("cleanUp", () => { + let now = Date.now(); + + for (let i = 0; i < 1002; i++) { + insertJobHistory({ + job_name: "test", + response_ok: 1, + response_status: 200, + response_text: "", + triggered_at: now++, + }); + } + + expect(getCount()).toEqual(1002); + cleanUp(now); + expect(getCount()).toEqual(1002); + cleanUp(now + 1000 * 60 * 60 + 1); + expect(getCount()).toEqual(1000); +}); diff --git a/src/history.ts b/src/history.ts index 1153d20..80e06f5 100644 --- a/src/history.ts +++ b/src/history.ts @@ -1,19 +1,18 @@ import { Database, Statement } from "bun:sqlite"; +export let db: Database; + let insertQuery: Statement; let getQuery: Statement; let countQuery: Statement; - -let initialized = false; - -export let db: Database; +let deleteOldQuery: Statement; export function init(path = "db/history.sqlite") { - if (initialized) return; + if (db) return; - const d = new Database(path); - d.run("PRAGMA journal_mode = WAL;"); - d.run(` + db = new Database(path); + db.run("PRAGMA journal_mode = WAL;"); + db.run(` create table if not exists jobs_history ( job_name text not null, triggered_at number not null, @@ -21,21 +20,21 @@ export function init(path = "db/history.sqlite") { response_status number not null, response_text text not null );`); - d.run( + db.run( `create index if not exists jobs_history_index on jobs_history (job_name);` ); - insertQuery = d.query( + insertQuery = db.query( `insert into jobs_history (job_name, triggered_at, response_ok, response_status, response_text) values ($job_name, $triggered_at, $response_ok, $response_status, $response_text);` ); - getQuery = d.query( + getQuery = db.query( "select * from jobs_history where job_name = ? ORDER BY triggered_at DESC LIMIT ? OFFSET ?;" ); - countQuery = d.query("select COUNT(*) from jobs_history"); - - initialized = true; + countQuery = db.query("select COUNT(*) from jobs_history;"); - db = d; + deleteOldQuery = db.query( + "delete from jobs_history where triggered_at in (select triggered_at from jobs_history order by triggered_at asc limit (select count(*) - 1000 from jobs_history));" + ); } export function truncate() { @@ -52,20 +51,36 @@ export type JobHistory = { export function insertJobHistory(h: JobHistory) { init(); - return insertQuery.run({ + + insertQuery.run({ $job_name: h.job_name, $triggered_at: h.triggered_at, $response_ok: h.response_ok, $response_status: h.response_status, $response_text: h.response_text, }); + cleanUp(Date.now()); } -export function getJobHistoryByName(name: string, limit = 1000, offset = 0) { +const oneHour = 1000 * 60 * 60; +let lastCleanup = Date.now(); +export function cleanUp(now: number) { + init(); + if (now - lastCleanup < oneHour) return; + if (getCount() <= 1000) return; + lastCleanup = now; + deleteOldQuery.run(); +} + +export function getCount() { init(); const countRow = countQuery.get(); - const count = countRow["COUNT(*)"]; + return countRow["COUNT(*)"]; +} +export function getJobHistoryByName(name: string, limit = 1000, offset = 0) { + init(); + const count = getCount(); const history = getQuery.all(name, limit, offset) as JobHistory[]; return { history, count };