diff --git a/public/index.html b/public/index.html
index 24e5b31..658dbba 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1269,6 +1269,17 @@ function renderNetworkMap(d) {
if (markers.length === 0) { mapEl.classList.add('hidden'); return; }
mapEl.classList.remove('hidden');
+ // Defer map init to next frame so container has real dimensions after display:none removal
+ window._pcMapMarkers = markers;
+ window._pcMapFacs = facs;
+ requestAnimationFrame(function() {
+ requestAnimationFrame(function() {
+ _initLeafletMap(mapDiv, window._pcMapMarkers, window._pcMapFacs);
+ });
+ });
+}
+
+function _initLeafletMap(mapDiv, markers, facs) {
if (_pcMap) { _pcMap.remove(); _pcMap = null; }
_pcMap = L.map(mapDiv, { scrollWheelZoom: false, attributionControl: false });
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
@@ -1323,7 +1334,7 @@ function renderNetworkMap(d) {
_pcMap.invalidateSize();
_pcMap.fitBounds(bounds, { padding: [30, 30], maxZoom: 6 });
}
- }, 200);
+ }, 500);
}
diff --git a/server.js b/server.js
index e4b77f1..2befb41 100644
--- a/server.js
+++ b/server.js
@@ -2875,9 +2875,23 @@ function fetchAllAtlasProbes() {
let pdbOrgCountryMap = new Map(); // org_id → { country, name }
function fetchPdbOrgCountries() {
- console.log("[PDB-ORG] Fetching PeeringDB org countries...");
+ var cacheFile = require("path").join(__dirname, ".pdb-org-cache.json");
+ var fs = require("fs");
+
+ // Try disk cache first (valid for 24h)
+ try {
+ var stat = fs.statSync(cacheFile);
+ var ageHours = (Date.now() - stat.mtimeMs) / 3600000;
+ if (ageHours < 24) {
+ var cached = JSON.parse(fs.readFileSync(cacheFile, "utf8"));
+ pdbOrgCountryMap = new Map(Object.entries(cached));
+ console.log("[PDB-ORG] Loaded " + pdbOrgCountryMap.size + " orgs from disk cache (" + Math.round(ageHours) + "h old)");
+ return Promise.resolve();
+ }
+ } catch (_) { /* no cache or invalid */ }
+
+ console.log("[PDB-ORG] Fetching PeeringDB org countries (fresh)...");
return new Promise(function(resolve) {
- // Use raw https to handle the large 16MB response with streaming
var chunks = [];
var req = require("https").get("https://www.peeringdb.com/api/org?status=ok&depth=0", {
headers: {
@@ -2886,6 +2900,11 @@ function fetchPdbOrgCountries() {
},
timeout: 120000,
}, function(res) {
+ if (res.statusCode !== 200) {
+ console.error("[PDB-ORG] HTTP " + res.statusCode + " — using stale cache or empty");
+ resolve();
+ return;
+ }
res.on("data", function(chunk) { chunks.push(chunk); });
res.on("end", function() {
try {
@@ -2893,12 +2912,16 @@ function fetchPdbOrgCountries() {
var data = JSON.parse(body);
if (data && data.data) {
pdbOrgCountryMap = new Map();
+ var cacheObj = {};
data.data.forEach(function(o) {
if (o.id && o.country) {
pdbOrgCountryMap.set(o.id, { country: o.country, name: o.name || "" });
+ cacheObj[o.id] = { country: o.country, name: o.name || "" };
}
});
- console.log("[PDB-ORG] Loaded " + pdbOrgCountryMap.size + " org→country mappings");
+ // Save to disk cache
+ try { fs.writeFileSync(cacheFile, JSON.stringify(cacheObj)); } catch (_) {}
+ console.log("[PDB-ORG] Loaded " + pdbOrgCountryMap.size + " org→country mappings (cached to disk)");
}
} catch (e) {
console.error("[PDB-ORG] Parse error:", e.message);