mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 12:27:07 +00:00
84 lines
2.1 KiB
JavaScript
84 lines
2.1 KiB
JavaScript
|
|
const { listen } = require('../../../ws/db');
|
||
|
|
|
||
|
|
// Event responses take a long time as we are querying a view
|
||
|
|
// which is the union of other views and non-optimised tables,
|
||
|
|
// so to speed things up a bit for the user we cache the
|
||
|
|
// results here.
|
||
|
|
// We do this by indexing each result by its ETag value and
|
||
|
|
// storing the ID of the project it belongs to as well as the
|
||
|
|
// timestamp of the request. If the events for a project are
|
||
|
|
// modified in any way (addition/deletion/change) we immediately
|
||
|
|
// invalidate all cached responses for that project, else we
|
||
|
|
// delete them when they're older than maxAge (plus a delay).
|
||
|
|
// When the user sends a request with an ETag, we search for
|
||
|
|
// the ETag in our cache and return that, if present, instead
|
||
|
|
// of hitting the database.
|
||
|
|
|
||
|
|
const cache = {};
|
||
|
|
const maxAge = 90*60*1000; // 1.5 hours
|
||
|
|
setInterval(() => {
|
||
|
|
const now = Date.now();
|
||
|
|
for (const key in cache) {
|
||
|
|
const value = cache[key];
|
||
|
|
if ((now - value.tstamp) > maxAge) {
|
||
|
|
// console.log("CLEARING", key);
|
||
|
|
delete cache[key];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}, 5*60*1000); // Run every five minutes
|
||
|
|
|
||
|
|
listen(["event"], (data) => {
|
||
|
|
for (const key in cache) {
|
||
|
|
const value = cache[key];
|
||
|
|
if (value.pid == data.payload.pid) {
|
||
|
|
delete cache[key];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
function get (req, res, next) {
|
||
|
|
try {
|
||
|
|
// console.log(cache);
|
||
|
|
const etag = req.get('if-none-match');
|
||
|
|
// console.log("ETag", etag);
|
||
|
|
if (etag && cache[etag]) {
|
||
|
|
// console.log("In cache");
|
||
|
|
if (cache[etag].headers) {
|
||
|
|
for (const header in cache[etag].headers) {
|
||
|
|
const value = cache[etag].headers[header];
|
||
|
|
if (header && value) {
|
||
|
|
res.set(header, value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 304s have no body
|
||
|
|
// https://tools.ietf.org/html/rfc7232#section-4.1
|
||
|
|
res.status(304).send();
|
||
|
|
next('route');
|
||
|
|
} else {
|
||
|
|
// console.log("Not in cache");
|
||
|
|
next();
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
next(err);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function save (req, res, next) {
|
||
|
|
const etag = res.getHeader("etag");
|
||
|
|
if (etag) {
|
||
|
|
cache[etag] = {
|
||
|
|
headers: {
|
||
|
|
"Content-Type": res.getHeader("content-type") || "application/json"
|
||
|
|
},
|
||
|
|
pid: req.params.project,
|
||
|
|
tstamp: Date.now()
|
||
|
|
}
|
||
|
|
// console.log("CACHE", cache);
|
||
|
|
}
|
||
|
|
|
||
|
|
next();
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = { get, save };
|