Keep the news layer inside its day and its memory bounds

From review of the news layer:
- An event's other sides older than 24 hours (or undated) are no longer
  listed, and a report dated more than 15 minutes ahead is outside the
  window, as in the regional brief.
- Picture cards are one canvas per event in a bounded cache (24), repainted
  in place when the age changes, with each card's picture dropped with it;
  the age in the key had made a new canvas every minute.
- The feed list drops reports that leave the window and is capped at 600.
- "In view" is filtered from the reports the layer already holds; it reads
  the feed only with minor news on, once per refresh, never per pan.
- Infinite scroll restarts after a filter change or a failed read.
- The two filter selects stack, so "Significant and above" is not cut off.
- The timeout tests hold the event loop until aborted, so they pass on
  Node 22 as well.
This commit is contained in:
Denis Groshev committed 2026-11-06 00:45:25 +01:00
1 parent 138cc77a11
commit e95ae7b80c
11 files changed
+560 -90

No files matched your search

+9 -3
View File
@@ -124,10 +124,16 @@ test('upstream failures, bad JSON and timeouts become bounded errors', async ()
const slow = mount({
origin: () => 'https://news.example',
timeoutMs: 10,
// AbortSignal.timeout does not hold the event loop open: the hanging
// fetch does, until its signal aborts, so the run cannot end before it.
fetchImpl: (_url, { signal }) =>
new Promise((_, reject) =>
signal.addEventListener('abort', () => reject(signal.reason)),
),
new Promise((_, reject) => {
const alive = setTimeout(() => {}, 60_000);
signal.addEventListener('abort', () => {
clearTimeout(alive);
reject(signal.reason);
});
}),
});
const timedOut = await slow('/hotspots');
assert.equal(timedOut.status, 504);