PeerCortex/server/caches/pdb-source-cache.js
Rene Fichtmueller e5c1c2a6ae refactor: extract cache modules from server.js (roaStore, pdbSourceCache, response caches)
Also drops confirmed-dead code found during extraction: unused TIER1_ASNS
require (its only consumer, computeRouteLeakDetection, already moved to
server/route-leak.js with its own require) and bgproutesVpCache/
bgproutesVpCacheTs/BGPROUTES_VP_TTL (declared, never read anywhere).

Verified via smoke-test harness (28/28 match). server.js: 6302 -> 5907 lines.
2026-07-16 23:28:00 +02:00

86 lines
2.9 KiB
JavaScript

const fs = require("fs");
// PeeringDB Source Cache (L2) — net/netixlan/netfac per ASN
// Eliminates redundant PDB API calls under load
const pdbSourceCache = {
net: new Map(), // key: asn string → {data, ts}
netixlan: new Map(), // key: net_id string → {data, ts}
netfac: new Map(), // key: net_id string → {data, ts}
facCoords: new Map(), // key: fac_id string → {lat, lon, ts}
TTL_NET: 6 * 60 * 60 * 1000, // 6 hours
TTL_IXFAC: 6 * 60 * 60 * 1000, // 6 hours
TTL_COORDS: 7 * 24 * 60 * 60 * 1000, // 7 days
MAX_NET: 5000,
MAX_IXFAC: 5000,
MAX_COORDS: 10000,
hits: 0,
misses: 0,
get(type, key) {
const map = this[type];
const ttl = type === "facCoords" ? this.TTL_COORDS : (type === "net" ? this.TTL_NET : this.TTL_IXFAC);
const entry = map.get(String(key));
if (!entry) { this.misses++; return null; }
if (Date.now() - entry.ts > ttl) { map.delete(String(key)); this.misses++; return null; }
this.hits++;
return entry.data;
},
set(type, key, data) {
const map = this[type];
const max = type === "facCoords" ? this.MAX_COORDS : (type === "net" ? this.MAX_NET : this.MAX_IXFAC);
if (map.size >= max) {
// Evict oldest entry (Map preserves insertion order)
map.delete(map.keys().next().value);
}
map.set(String(key), { data, ts: Date.now() });
},
// Disk persistence
saveToDisk(filePath) {
try {
const serialize = (map) => {
const obj = {};
for (const [k, v] of map) obj[k] = v;
return obj;
};
const data = JSON.stringify({
ts: Date.now(),
net: serialize(this.net),
netixlan: serialize(this.netixlan),
netfac: serialize(this.netfac),
facCoords: serialize(this.facCoords),
});
fs.writeFileSync(filePath, data);
console.log("[PDB-CACHE] Saved to disk (net=" + this.net.size + " ix=" + this.netixlan.size + " fac=" + this.netfac.size + ")");
} catch (e) {
console.warn("[PDB-CACHE] Disk save failed:", e.message);
}
},
loadFromDisk(filePath) {
try {
if (!fs.existsSync(filePath)) return false;
const raw = fs.readFileSync(filePath, "utf8");
const data = JSON.parse(raw);
const now = Date.now();
const load = (map, obj, ttl) => {
for (const [k, v] of Object.entries(obj || {})) {
if (now - v.ts < ttl) map.set(k, v);
}
};
load(this.net, data.net, this.TTL_NET);
load(this.netixlan, data.netixlan, this.TTL_IXFAC);
load(this.netfac, data.netfac, this.TTL_IXFAC);
load(this.facCoords, data.facCoords, this.TTL_COORDS);
console.log("[PDB-CACHE] Loaded from disk (net=" + this.net.size + " ix=" + this.netixlan.size + " fac=" + this.netfac.size + ")");
return true;
} catch (e) {
console.warn("[PDB-CACHE] Disk load failed:", e.message);
return false;
}
},
};
module.exports = { pdbSourceCache };