Add refresh-project-summary periodic task.

It listens for events that might indicate that the project_summary
materialised view needs to be refreshed and schedules a refresh.

Refreshes are throttled to a maximum of one every throttlePeriod
milliseconds so that things don't get too crazy for instance when
importing a lot of data.
This commit is contained in:
D. Berge
2023-11-02 11:59:42 +01:00
parent cb35e340e1
commit b148ed2368
2 changed files with 87 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
module.exports = [
require('./purge-notifications')
require('./purge-notifications'),
require('./refresh-project-summary')
];

View File

@@ -0,0 +1,85 @@
const db = require('../../lib/db');
const { listen } = require('../../lib/db/notify');
const { ALERT, ERROR, WARNING, NOTICE, INFO, DEBUG } = require('DOUGAL_ROOT/debug')(__filename);
const timeout = 30*1000;
async function init () {
INFO("Setting up task");
// Full list of channels in
// ../lib/db/channels
const channels = [
"project",
"preplot_lines", "preplot_points",
"raw_lines", "raw_shots",
"final_lines", "final_shots"
];
const throttlePeriod = 10*1000;
const projects = {};
listen (channels, (data) => {
// Something important has changed,
// set the dirty flag for the relevant project
const pid = data.payload?.pid ?? data.payload?.new?.pid ?? data.payload?.old?.pid;
if (pid) {
if (!pid in projects) {
projects[pid] = {
lastRefreshed: 0
};
}
if (!projects[pid].needsRefresh) {
projects[pid].needsRefresh = true;
DEBUG("Setting up refresh flag for %s: %j", pid, projects[pid]);
}
}
});
const task = async () => {
for (pid in projects) {
const project = projects[pid];
if (project.needsRefresh) {
const now = Date.now();
const lastRefreshAge = now - project.lastRefreshed;
if (lastRefreshAge > throttlePeriod) {
// Do the actual refresh
try {
DEBUG("Refreshing", pid);
await db.project.summary.refresh(pid);
} catch (err) {
if (err.status == 404) {
DEBUG("Project %s not found. Removing from refresh list", pid);
delete projects[pid];
} else {
ERROR(err);
}
}
project.needsRefresh = false;
project.lastRefreshed = now;
}
}
}
};
// Let us populate the project list and do a first refresh on startup
for (const project of await db.project.get()) {
projects[project.pid] = {
lastRefreshed: 0,
needsRefresh: true
}
}
task(); // No need to await
return task;
}
async function cleanup () {
}
module.exports = {
init,
timeout,
cleanup
};