Repository navigation
Expand file tree
/
Copy pathpi-handoff.js
More file actions
108 lines (94 loc) · 2.5 KB
/
Copy pathpi-handoff.js
File metadata and controls
108 lines (94 loc) · 2.5 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
'use strict';
/**
* In-run handoff of PI episode payloads from stage 3 → stage 4 so vectorize
* does not re-fetch the same shows in the same pipeline run.
*
* Keeps the map in memory during the run; flushes to disk periodically and
* at end of stage 3. (Per-put full-file writes made stage 3 crawl as the
* map grew.)
*/
const fs = require('fs');
const cfg = require('./config');
const FLUSH_EVERY = 100;
/** @type {Record<string, object[]>|null} */
let mem = null;
let dirty = 0;
let putsSinceFlush = 0;
function handoffPath() {
return cfg.PI_EPISODE_HANDOFF_FILE;
}
function clear() {
mem = {};
dirty = 0;
putsSinceFlush = 0;
try {
fs.writeFileSync(handoffPath(), '{}');
} catch {
// best-effort
}
}
function load() {
if (mem) return mem;
try {
const raw = fs.readFileSync(handoffPath(), 'utf8');
const data = JSON.parse(raw);
mem = data && typeof data === 'object' ? data : {};
} catch {
mem = {};
}
return mem;
}
function flushSync() {
if (!mem) return;
fs.writeFileSync(handoffPath(), JSON.stringify(mem));
dirty = 0;
putsSinceFlush = 0;
}
/**
* Store episodes for one show. Memory-only unless FLUSH_EVERY reached.
* Prefer storing only when stage 4 may need them (caller decides).
*/
function put(podcastId, episodes) {
const map = load();
map[String(podcastId)] = episodes || [];
dirty = 1;
putsSinceFlush++;
if (putsSinceFlush >= FLUSH_EVERY) {
flushSync();
}
}
/** Durable flush before stage 4. */
async function flush() {
flushSync();
}
/** @returns {object[]|null} */
function take(podcastId) {
const map = load();
const key = String(podcastId);
if (!Object.prototype.hasOwnProperty.call(map, key)) return null;
return map[key];
}
/** Drop same-run payload for deleted / completed shows (memory + next flush). */
function remove(podcastId) {
const map = load();
const key = String(podcastId);
if (!Object.prototype.hasOwnProperty.call(map, key)) return;
delete map[key];
dirty = 1;
}
/**
* @param {Array<string|number>} podcastIds
*/
function removeMany(podcastIds) {
const map = load();
let changed = false;
for (const id of podcastIds || []) {
const key = String(id);
if (Object.prototype.hasOwnProperty.call(map, key)) {
delete map[key];
changed = true;
}
}
if (changed) dirty = 1;
}
module.exports = { clear, load, put, take, remove, removeMany, flush, handoffPath };