fix(gnss): age degraded evidence and replayed snapshots on their own clocks

Maintainer review on #855 (mazy1998, 2026-10-06):

- records: presence (seenAt) and degraded evidence (degradedAt) age
  separately, so continuing healthy reports no longer keep an older
  degraded flag alive past 30 minutes; an aircraft returning after the
  window starts fresh. pruneGnssObservations ages the store with no new
  rows.
- Rows are dated by the snapshot's fetchedAt, which the proxy keeps on
  cached and stale answers: a replay never restarts the window, the
  proxy stops serving a stale snapshot older than the window, the source
  refuses an undated one, and cells expire during fetch failures and
  while there is no view anchor.
- Normalization accepts ADS-B versions 1 and 2 only; a missing, invalid
  or negative seen_pos is not a confirmed position from the last minute.
- qa-gnss: keyboard, 390x844 viewport (fresh page: isMobile reloads) and
  replay-age sections; the live cell assertion bins the returned rows
  with the layer's own rules instead of a raw row count.
This commit is contained in:
Leo Pechnicki authored and Mazeyar Moeini Feizabadi committed 2026-10-13 17:20:43 +02:00
1 parent c8d3f44bb7
commit fde8b2a64f
11 files changed
+557 -65

No files matched your search

+5 -1
View File
@@ -1,5 +1,6 @@
import {
GNSS_CLASSIFIER,
GNSS_WINDOW_MS,
normalizeGnssAircraft,
} from '../../src/layers/gnss/records.js';
import { adsbLolFallbackAnchor } from './aircraft/opensky.js';
@@ -115,7 +116,10 @@ export function gnssIntegrityProxy({
});
return { value: await promise, stale: false };
} catch (error) {
if (previous) return { value: previous, stale: true };
// A stale answer keeps its original fetchedAt so the layer can age it;
// past the layer's window it is no evidence at all, so it is not served.
if (previous && now() - previous.fetchedAt <= GNSS_WINDOW_MS)
return { value: previous, stale: true };
throw error;
}
}