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.
86 lines
2.9 KiB
JavaScript
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 };
|