Retry transient chart detail misses
This commit is contained in:
@@ -64,6 +64,7 @@ const PROBABILITY_REFRESH_AFTER_PATCH_MS = DASHBOARD_REFRESH_POLICY_MS.metar;
|
||||
const FOREGROUND_FULL_DETAIL_REFRESH_DEDUP_MS = 90_000;
|
||||
const NO_PATCH_CACHED_DETAIL_REFRESH_MS = DASHBOARD_REFRESH_POLICY_MS.observation;
|
||||
const DETAIL_LOAD_BATCH_DELAY_MS = 0;
|
||||
const TRANSIENT_DETAIL_RETRY_DELAY_MS = 3_000;
|
||||
const INITIAL_DETAIL_LOAD_SLOTS = 3;
|
||||
const DEFERRED_DETAIL_LOAD_DELAY_MS = 1_200;
|
||||
const DEFERRED_DETAIL_LOAD_GROUP_SIZE = 3;
|
||||
@@ -792,13 +793,41 @@ export function LiveTemperatureThresholdChart({
|
||||
setIsHourlyLoading(true);
|
||||
markDetailRequest("network");
|
||||
let cancelled = false;
|
||||
let retryScheduled = false;
|
||||
let retryTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
const scheduleTransientDetailRetry = () => {
|
||||
retryScheduled = true;
|
||||
markDetailDegraded();
|
||||
retryTimer = setTimeout(() => {
|
||||
if (cancelled) return;
|
||||
markDetailRequest("network");
|
||||
fetchHourlyForecastForCity(city, { bypassLocalCache: true, resolution: targetResolution })
|
||||
.then((data) => {
|
||||
if (cancelled) return;
|
||||
if (!data) {
|
||||
markDetailDegraded({ showUserError: true });
|
||||
return;
|
||||
}
|
||||
applySuccessfulHourlyDetail(data);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
markDetailDegraded({ showUserError: true });
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setIsHourlyLoading(false);
|
||||
});
|
||||
}, TRANSIENT_DETAIL_RETRY_DELAY_MS);
|
||||
};
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
fetchHourlyForecastForCity(city, { resolution: targetResolution })
|
||||
.then((data) => {
|
||||
if (cancelled) return;
|
||||
if (!data) {
|
||||
markDetailDegraded({ showUserError: true });
|
||||
scheduleTransientDetailRetry();
|
||||
return;
|
||||
}
|
||||
applySuccessfulHourlyDetail(data);
|
||||
@@ -809,13 +838,14 @@ export function LiveTemperatureThresholdChart({
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setIsHourlyLoading(false);
|
||||
if (!cancelled && !retryScheduled) setIsHourlyLoading(false);
|
||||
});
|
||||
}, DETAIL_LOAD_BATCH_DELAY_MS);
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearTimeout(timer);
|
||||
if (retryTimer !== null) clearTimeout(retryTimer);
|
||||
};
|
||||
}, [
|
||||
city,
|
||||
|
||||
@@ -299,6 +299,13 @@ export async function runTests() {
|
||||
chartCanvasSourceIncludes(chartSource, "handleRetryDetail"),
|
||||
"city detail charts should show stale cache first and expose a retryable unavailable state",
|
||||
);
|
||||
assert(
|
||||
chartSource.includes("TRANSIENT_DETAIL_RETRY_DELAY_MS") &&
|
||||
chartSource.includes("scheduleTransientDetailRetry") &&
|
||||
chartSource.includes("fetchHourlyForecastForCity(city, { bypassLocalCache: true, resolution: targetResolution })") &&
|
||||
chartSource.includes("!retryScheduled"),
|
||||
"cold partial detail-batch misses should stay in loading state and retry cached detail once before showing unavailable",
|
||||
);
|
||||
const successfulHourlyDetailBlock =
|
||||
/const applySuccessfulHourlyDetail = useCallback\([\s\S]*?\n \}, \[row\]\);/.exec(chartSource)?.[0] || "";
|
||||
assert(
|
||||
|
||||
Reference in New Issue
Block a user