fix(phase26): revert batch geocode, use rate-limited concurrent requests to avoid server freeze

This commit is contained in:
Mathieu Moran
2026-08-11 04:57:44 -04:00
parent 5018c6c531
commit ad56380e23
+25 -21
View File
@@ -36,10 +36,17 @@
let _geoCache = {}; // key → label, pre-populated on trip load let _geoCache = {}; // key → label, pre-populated on trip load
function _geoKey(lat, lon) { function _geoKey(lat, lon) {
return `${lat.toFixed(3)},${lon.toFixed(3)}`; const la = typeof lat === 'number' ? lat : parseFloat(lat);
const lo = typeof lon === 'number' ? lon : parseFloat(lon);
if (isNaN(la) || isNaN(lo)) return null;
return `${la.toFixed(3)},${lo.toFixed(3)}`;
} }
function preloadGeocodes(points) { 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.
_geoCache = {}; _geoCache = {};
const seen = new Set(); const seen = new Set();
const queue = []; const queue = [];
@@ -51,30 +58,27 @@
} }
if (!queue.length) return; if (!queue.length) return;
// Try batch endpoint first (server has it, Pi falls back to 404) const CONCURRENCY = 2;
const coords = queue.map(q => ({lat: q.lat, lon: q.lon})); let idx = 0;
const ctrl = new AbortController(); function next() {
const t = setTimeout(() => ctrl.abort(), 15000); if (idx >= queue.length) return;
fetch('/api/geocode/batch', { const item = queue[idx++];
method: 'POST', const ctrl = new AbortController();
headers: {'Content-Type': 'application/json'}, const t = setTimeout(() => ctrl.abort(), 3000);
body: JSON.stringify({coords: coords}), fetch(`/api/geocode?lat=${item.lat}&lon=${item.lon}`, { signal: ctrl.signal })
signal: ctrl.signal, .then(r => { clearTimeout(t); return r.ok ? r.json() : null; })
}) .then(data => {
.then(r => { clearTimeout(t); return r.ok ? r.json() : null; }) _geoCache[item.key] = (data && data.label) || null;
.then(data => { })
if (data) { .catch(() => { clearTimeout(t); })
for (const q of queue) { .finally(() => next());
if (data[q.key]) _geoCache[q.key] = data[q.key]; }
} for (let i = 0; i < CONCURRENCY && i < queue.length; i++) next();
}
})
.catch(() => { clearTimeout(t); });
} }
function geocodePoint(lat, lon) { function geocodePoint(lat, lon) {
const key = _geoKey(lat, lon); const key = _geoKey(lat, lon);
if (key === _lastGeoKey) return; if (!key || key === _lastGeoKey) return;
_lastGeoKey = key; _lastGeoKey = key;
const fallback = `${lat.toFixed(5)}, ${lon.toFixed(5)}`; const fallback = `${lat.toFixed(5)}, ${lon.toFixed(5)}`;