Repository navigation
Expand file tree
/
Copy pathknowledgeCleanup.js
More file actions
38 lines (37 loc) · 1.61 KB
/
Copy pathknowledgeCleanup.js
File metadata and controls
38 lines (37 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Mandatory metadata retention, not publication or a conversation observer.
// It remains available with both the inbox and memory switches off.
function createKnowledgeCleanup({ store, track = operation => operation(), now = Date.now,
stopping = () => false, setTimer = setTimeout, clearTimer = clearTimeout,
logUnavailable = () => console.error('[KnowledgeReview] retention cleanup unavailable; pending retry') } = {}) {
if (!store?.pruneExpiredProvenance) throw Error('A provenance cleanup store is required');
let started = false, stopped = false, timer, pending;
const unavailable = () => stopped || stopping();
function schedule(delay) {
if (unavailable()) return;
timer = setTimer(() => { timer = undefined; run(); }, delay);
timer.unref?.();
}
function run() {
if (!started || unavailable()) return Promise.resolve(null);
if (pending) return pending;
if (timer) { clearTimer(timer); timer = undefined; }
let nextDelay = 60000;
pending = Promise.resolve().then(() => {
if (unavailable()) return null;
return track(() => store.pruneExpiredProvenance(now(), { shouldStop: unavailable }));
}).then(result => {
if (result?.remaining) nextDelay = 250;
return result;
}).catch(() => {
logUnavailable();
return null;
}).finally(() => { pending = null; schedule(nextDelay); });
return pending;
}
return {
start() { if (started) return pending || Promise.resolve(null); started = true; return run(); },
run,
stop() { stopped = true; if (timer) clearTimer(timer); timer = undefined; },
};
}
module.exports = { createKnowledgeCleanup };