storing last run in database

This commit is contained in:
orangecoding
2026-06-09 16:52:37 +02:00
parent 6bef907416
commit bc9c56a224
9 changed files with 287 additions and 85 deletions

View File

@@ -104,7 +104,6 @@ export function initJobExecutionService({ providers, settings, intervalMs }) {
logger.debug('Working hours set. Skipping as outside of working hours.');
return;
}
settings.lastRun = now;
const jobs = jobStorage.getJobs().filter((job) => {
if (!context) return true; // startup/cron → all
if (context.isAdmin) return true; // admin → all
@@ -150,6 +149,13 @@ export function initJobExecutionService({ providers, settings, intervalMs }) {
}
const acquired = markRunning(job.id);
if (!acquired) return;
// Persist the trigger time so the dashboard "last search" KPI can be
// derived per accessible user without an in-memory cache.
try {
jobStorage.updateJobLastRunAt(job.id, Date.now());
} catch (err) {
logger.warn('Failed to persist last_run_at for job', job.id, err);
}
// notify listeners (SSE) that the job started
try {
bus.emit('jobs:status', { jobId: job.id, running: true });

View File

@@ -97,6 +97,7 @@ export const getJob = (jobId) => {
j.notification_adapter AS notificationAdapter,
j.spatial_filter AS spatialFilter,
j.spec_filter AS specFilter,
j.last_run_at AS lastRunAt,
(SELECT COUNT(1) FROM listings l WHERE l.job_id = j.id AND l.is_active = 1 AND l.manually_deleted = 0) AS numberOfFoundListings
FROM jobs j
WHERE j.id = @id
@@ -116,6 +117,24 @@ export const getJob = (jobId) => {
};
};
/**
* Record the timestamp at which a job was last triggered.
*
* Called from the job execution service when a job starts running. The value
* is persisted so that the dashboard "last search" KPI survives restarts and
* can be computed per accessible user.
*
* @param {string} jobId - Job primary key.
* @param {number} timestamp - Epoch milliseconds.
* @returns {void}
*/
export const updateJobLastRunAt = (jobId, timestamp) => {
SqliteConnection.execute(`UPDATE jobs SET last_run_at = @timestamp WHERE id = @id`, {
id: jobId,
timestamp,
});
};
/**
* Update job enabled status.
* @param {{jobId: string, status: boolean}} params - Parameters.
@@ -164,6 +183,7 @@ export const getJobs = () => {
j.notification_adapter AS notificationAdapter,
j.spatial_filter AS spatialFilter,
j.spec_filter AS specFilter,
j.last_run_at AS lastRunAt,
(SELECT COUNT(1) FROM listings l WHERE l.job_id = j.id AND l.is_active = 1 AND l.manually_deleted = 0) AS numberOfFoundListings
FROM jobs j
WHERE j.enabled = 1
@@ -269,6 +289,7 @@ export const queryJobs = ({
j.notification_adapter AS notificationAdapter,
j.spatial_filter AS spatialFilter,
j.spec_filter AS specFilter,
j.last_run_at AS lastRunAt,
(SELECT COUNT(1) FROM listings l WHERE l.job_id = j.id AND l.is_active = 1 AND l.manually_deleted = 0) AS numberOfFoundListings
FROM jobs j
${whereSql}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2026 by Christian Kellner.
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
/**
* Migration: add `last_run_at` to the `jobs` table.
*
* Stores the epoch-ms timestamp at which a job was last triggered. Used by the
* dashboard "last search" KPI so the value survives restarts and reflects the
* actual jobs the requesting user can see (own, shared, or all for admins),
* replacing the previous in-memory `settings.lastRun` value.
*
* NULL means the job has not yet been triggered since this column was added.
*/
export function up(db) {
db.exec(`
ALTER TABLE jobs ADD COLUMN last_run_at INTEGER
`);
}