fix(terrain): keep cold height requests within the browser deadline (#348)

Use 64-point browser and upstream terrain batches to reduce cold-cache timeouts. Preserve successful chunk results, distinguish absent readings from malformed responses, and reject fabricated zero heights.

Original terrain resilience contribution by ItzDESTAQ, with browser batching, validation and regression follow-up by Sameh Khamis.

Validated with unit/build/format/boundary checks, 108 tracking checks, 5 terrain-outage checks, controlled slow-upstream comparison and live browser checks.

Co-authored-by: ItzDESTAQ <[email protected]>
Co-authored-by: Sameh Khamis <[email protected]>
This commit is contained in:
DESTAQandSameh Khamis authored and GitHub committed 2026-09-12 14:04:08 -07:00
1 parent 4e99f40488
commit db49edf363
8 files changed
+254 -32

No files matched your search

+43 -8
View File
@@ -60,6 +60,28 @@ export function validTerrainResult(result) {
return Boolean(result) && Number.isFinite(result.ellipsoid);
}
/**
* A row the upstream DID return for its position, but with no usable height:
* Re:Earth sporadically answers with a real `elevation` and a null
* `geoid`/`ellipsoid`. Measured at ~0.16% of points, and transient — the same
* coordinate resolves on a later poll. That is an absent datum, not a failed
* refresh, so the point is left uncached to be re-asked while the client
* covers it through its bundled geoid. A null/undefined entry is NOT this
* case: it means the position was dropped from the response, which is a
* genuine upstream fault.
* @param {unknown} result
*/
export function absentTerrainDatum(result) {
return (
typeof result === 'object' &&
result !== null &&
!Array.isArray(result) &&
result.ellipsoid === null &&
result.geoid === null &&
Number.isFinite(result.elevation)
);
}
/**
* Convert Retry-After (delta-seconds or HTTP-date) to milliseconds.
* @param {string|null|undefined} value
@@ -194,24 +216,33 @@ export async function resolveTerrainHeightRequest({
let cacheChanged = false;
let upstreamError = null;
let absentPoints = 0;
if (missing.length > 0) {
try {
const fetched = await fetchMissing(missing.map((item) => item.point));
if (!Array.isArray(fetched))
throw new Error('malformed upstream response (no results array)');
const fetchedAt = now();
let omittedPositions = 0;
for (let i = 0; i < missing.length; i += 1) {
const result = fetched[i];
if (!validTerrainResult(result)) continue;
cache.set(missing[i].key, { at: fetchedAt, result });
cacheChanged = true;
if (validTerrainResult(result)) {
cache.set(missing[i].key, { at: fetchedAt, result });
cacheChanged = true;
} else if (absentTerrainDatum(result)) {
// Upstream answered but had no height. Transient, so deliberately
// left uncached: the next poll re-asks and usually succeeds.
absentPoints += 1;
} else {
// Missing or malformed positions remain upstream faults.
omittedPositions += 1;
}
}
if (
fetched.length !== missing.length ||
missing.some((_, i) => !validTerrainResult(fetched[i]))
) {
if (omittedPositions > 0 || fetched.length !== missing.length) {
const dropped =
omittedPositions || Math.abs(fetched.length - missing.length);
upstreamError = new Error(
'upstream omitted one or more terrain heights',
`upstream omitted ${dropped} terrain position(s)`,
);
}
} catch (error) {
@@ -232,6 +263,8 @@ export async function resolveTerrainHeightRequest({
},
cacheChanged,
upstreamError,
absentPoints,
requestedPoints: unique.size,
};
}
return {
@@ -239,5 +272,7 @@ export async function resolveTerrainHeightRequest({
body: { results },
cacheChanged,
upstreamError,
absentPoints,
requestedPoints: unique.size,
};
}