fix(phase26): abort preload fetches when switching trips to prevent server freeze

This commit is contained in:
Mathieu Moran
2026-08-11 05:01:18 -04:00
parent ad56380e23
commit cdb3fc19c7
+12 -9
View File
@@ -33,7 +33,8 @@
let _geoTimer = null;
let _lastGeoKey = null;
let _geoCache = {}; // key → label, pre-populated on trip load
let _geoCache = {};
let _preloadController = null;
function _geoKey(lat, lon) {
const la = typeof lat === 'number' ? lat : parseFloat(lat);
@@ -43,16 +44,17 @@
}
function preloadGeocodes(points) {
// Pre-fetch geocode labels for all unique coordinates with a small
// concurrency cap so the server (which uses slow Nominatim) doesn't
// get overwhelmed. The Pi's reverse_geocoder is instant, so this
// still works fast there.
// Abort any in-flight preload from a previous trip selection.
if (_preloadController) _preloadController.abort();
_preloadController = new AbortController();
const signal = _preloadController.signal;
_geoCache = {};
const seen = new Set();
const queue = [];
for (const p of points) {
const key = _geoKey(p.latitude, p.longitude);
if (seen.has(key)) continue;
if (!key || seen.has(key)) continue;
seen.add(key);
queue.push({ key, lat: p.latitude, lon: p.longitude });
}
@@ -61,17 +63,18 @@
const CONCURRENCY = 2;
let idx = 0;
function next() {
if (idx >= queue.length) return;
if (idx >= queue.length || signal.aborted) return;
const item = queue[idx++];
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 3000);
signal.addEventListener('abort', () => ctrl.abort());
fetch(`/api/geocode?lat=${item.lat}&lon=${item.lon}`, { signal: ctrl.signal })
.then(r => { clearTimeout(t); return r.ok ? r.json() : null; })
.then(data => {
_geoCache[item.key] = (data && data.label) || null;
if (!signal.aborted) _geoCache[item.key] = (data && data.label) || null;
})
.catch(() => { clearTimeout(t); })
.finally(() => next());
.finally(() => { if (!signal.aborted) next(); });
}
for (let i = 0; i < CONCURRENCY && i < queue.length; i++) next();
}