fix(frontend): keep the /cell prefetch seeding the dated grade URL
All checks were successful
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / changes (pull_request) Successful in 6s
secrets-guard / encrypted (pull_request) Successful in 5s
PR build (required check) / build-backend (pull_request) Has been skipped
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / build-frontend (pull_request) Successful in 29s
PR build (required check) / gate (pull_request) Successful in 3s
All checks were successful
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / changes (pull_request) Successful in 6s
secrets-guard / encrypted (pull_request) Successful in 5s
PR build (required check) / build-backend (pull_request) Has been skipped
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / build-frontend (pull_request) Successful in 29s
PR build (required check) / gate (pull_request) Successful in 3s
This commit is contained in:
parent
44b02d985a
commit
ab4ba54575
1 changed files with 15 additions and 6 deletions
|
|
@ -207,7 +207,7 @@ function seedCache(url, data, etag) {
|
|||
// lives here next to the bundle fetch — not knowledge of any one page.
|
||||
function viewFetches(q, today) {
|
||||
return {
|
||||
grade: [uv(`grade?${q}`), TTL.grade],
|
||||
grade: [uv(`grade?${q}&date=${today}`), TTL.grade],
|
||||
forecast: [uv(`forecast?${q}`), TTL.forecast],
|
||||
calendar: [uv(`calendar?${q}&months=24`), TTL.calendar],
|
||||
day: [uv(`day?${q}&date=${today}`), TTL.day],
|
||||
|
|
@ -232,6 +232,12 @@ export function prefetchViews(lat, lon, ownViews) {
|
|||
if (_prefetched === tag) return;
|
||||
_prefetched = tag;
|
||||
const q = `lat=${lat}&lon=${lon}`;
|
||||
// The client's local "today" — sent explicitly so the server never has to guess
|
||||
// it from its own (UTC) clock. Getting this wrong is exactly what poisoned the
|
||||
// Weekly view's cache for UTC+ visitors between their local midnight and UTC
|
||||
// midnight: the bundle used to be built against the server's date while the
|
||||
// per-view request stated the client's, so the two silently disagreed.
|
||||
const today = localDay();
|
||||
const own = new Set(ownViews);
|
||||
// Yield first so the landing view finishes rendering before we fetch the rest.
|
||||
setTimeout(async () => {
|
||||
|
|
@ -239,17 +245,20 @@ export function prefetchViews(lat, lon, ownViews) {
|
|||
const ek = "tg-cell-etag:" + q;
|
||||
let prev = null;
|
||||
try { prev = sessionStorage.getItem(ek); } catch (e) {}
|
||||
const res = await fetch(uv(`cell?${q}&neighbors=1`),
|
||||
const res = await fetch(uv(`cell?${q}&date=${today}&neighbors=1`),
|
||||
{ credentials: "include", ...(prev ? { headers: { "If-None-Match": prev } } : {}) });
|
||||
if (res.ok && res.status !== 304) {
|
||||
const bundle = await res.json();
|
||||
try { sessionStorage.setItem(ek, res.headers.get("ETag") || ""); } catch (e) {}
|
||||
const fetches = viewFetches(q, localDay());
|
||||
// Seed under bundle.today (the date the server actually resolved — normally
|
||||
// just an echo of the date= we sent) rather than our own `today`, so the
|
||||
// seeded key stays byte-identical to what a per-view request for that same
|
||||
// resolved date will use even in the rare case the two disagree (e.g. a
|
||||
// request that straddles local midnight).
|
||||
const fetches = viewFetches(q, bundle.today);
|
||||
for (const [name, slice] of Object.entries(bundle.slices || {})) {
|
||||
if (own.has(name) || !slice || !slice.data) continue;
|
||||
const url = name === "day"
|
||||
? uv(`day?${q}&date=${bundle.today}`) // the day slice targets today
|
||||
: (fetches[name] || [])[0];
|
||||
const url = (fetches[name] || [])[0];
|
||||
if (url) seedCache(url, slice.data, slice.etag);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue