UNPKG

@cadence-mq/driver-libsql

Version:
121 lines (117 loc) 3.42 kB
//#region src/driver.ts async function getAndMarkJobAsProcessing({ client, processingTimeoutMs, now = /* @__PURE__ */ new Date() }) { const transaction = await client.transaction("write"); try { const expiredAt = new Date(now.getTime() - processingTimeoutMs); const { rows } = await transaction.execute({ sql: "SELECT * FROM jobs WHERE status = 'pending' OR (status = 'processing' AND started_at < ?) ORDER BY schedule_at ASC LIMIT 1", args: [expiredAt] }); const [jobRow] = rows; if (!jobRow) { await transaction.rollback(); return { job: null }; } await transaction.execute({ sql: "UPDATE jobs SET status = 'processing', started_at = ? WHERE id = ? AND status = 'pending'", args: [now, jobRow.id] }); await transaction.commit(); return { job: toJob(jobRow) }; } catch (error) { await transaction.rollback(); throw error; } } function toJob(row) { return { id: String(row.id), taskName: String(row.task_name), status: row.status, startedAt: row.started_at ? new Date(String(row.started_at)) : void 0, completedAt: row.completed_at ? new Date(String(row.completed_at)) : void 0, maxRetries: Number(row.max_retries), data: row.data ? JSON.parse(String(row.data)) : void 0, result: row.result ? JSON.parse(String(row.result)) : void 0, scheduleAt: new Date(String(row.schedule_at)) }; } function createLibSqlDriver({ client, pollIntervalMs = 1e3 }) { return { fetchNextJob: async ({ processingTimeoutMs }) => { while (true) { const { job } = await getAndMarkJobAsProcessing({ client, processingTimeoutMs }); if (!job) { await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); continue; } return { job }; } }, saveJob: async ({ job, now = /* @__PURE__ */ new Date() }) => { await client.batch([{ sql: "INSERT INTO jobs (id, task_name, status, created_at, max_retries, data, schedule_at) VALUES (?, ?, ?, ?, ?, ?, ?)", args: [ job.id, job.taskName, job.status, now, job.maxRetries ?? null, JSON.stringify(job.data), job.scheduleAt ] }], "write"); }, markJobAsCompleted: async ({ jobId, now = /* @__PURE__ */ new Date(), result }) => { await client.batch([{ sql: "UPDATE jobs SET status = 'completed', completed_at = ?, result = ? WHERE id = ?", args: [ now, result ? JSON.stringify(result) : null, jobId ] }], "write"); }, markJobAsFailed: async ({ jobId, error }) => { await client.batch([{ sql: "UPDATE jobs SET status = ?, error = ? WHERE id = ?", args: [ "failed", error, jobId ] }], "write"); } }; } //#endregion //#region src/migrations.ts function getSchema() { return ` PRAGMA journal_mode = WAL; PRAGMA synchronous = 1; PRAGMA busy_timeout = 5000; CREATE TABLE IF NOT EXISTS jobs ( id TEXT PRIMARY KEY, task_name TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', created_at DATETIME NOT NULL, started_at DATETIME, completed_at DATETIME, max_retries INTEGER, data TEXT, result TEXT, schedule_at DATETIME NOT NULL ); CREATE INDEX IF NOT EXISTS jobs_status_schedule_at_started_at_idx ON jobs (status, schedule_at, started_at); `.trim(); } async function setupSchema({ client }) { await client.executeMultiple(getSchema()); } //#endregion export { createLibSqlDriver, getSchema, setupSchema }; //# sourceMappingURL=index.js.map