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