Reduce duplicate terminal detail loads

This commit is contained in:
2569718930@qq.com
2026-05-31 22:14:17 +08:00
parent 38c6cefb27
commit d911af1225
6 changed files with 262 additions and 51 deletions
@@ -56,6 +56,7 @@ const PEAK_GLOW_BADGE_CLASS = {
} as const;
const PROBABILITY_REFRESH_AFTER_PATCH_MS = 60_000;
const FOREGROUND_FULL_DETAIL_REFRESH_DEDUP_MS = 90_000;
const DETAIL_LOAD_BATCH_DELAY_MS = 0;
const TemperatureChartCanvas = dynamic(
@@ -165,6 +166,7 @@ export function LiveTemperatureThresholdChart({
const lastPatchAtRef = useRef<number>(Date.now());
const lastAppliedPatchRevisionRef = useRef<number>(0);
const lastProbabilityRefreshAtRef = useRef<number>(0);
const lastForegroundRefreshAtRef = useRef<number>(0);
const localDayRolloverFetchDateRef = useRef<string>("");
const [isChartVisible, setIsChartVisible] = useState(
() => typeof IntersectionObserver === "undefined",
@@ -197,6 +199,7 @@ export function LiveTemperatureThresholdChart({
lastPatchAtRef.current = Date.now();
lastAppliedPatchRevisionRef.current = 0;
lastProbabilityRefreshAtRef.current = 0;
lastForegroundRefreshAtRef.current = 0;
localDayRolloverFetchDateRef.current = "";
setCurrentCityLocalDate(formatCityLocalDate(row?.tz_offset_seconds));
}, [city]);
@@ -395,7 +398,19 @@ export function LiveTemperatureThresholdChart({
let cancelled = false;
const refreshForegroundFullDetail = () => {
lastPatchAtRef.current = Date.now();
const now = Date.now();
const cacheKey = `${city}:${targetResolution}`;
const cached = _hourlyCache.get(cacheKey);
const cacheAge = cached ? now - Number(cached.ts || 0) : Number.POSITIVE_INFINITY;
if (
now - lastForegroundRefreshAtRef.current < FOREGROUND_FULL_DETAIL_REFRESH_DEDUP_MS ||
(cacheAge >= 0 && cacheAge < FOREGROUND_FULL_DETAIL_REFRESH_DEDUP_MS)
) {
return;
}
lastForegroundRefreshAtRef.current = now;
lastPatchAtRef.current = now;
fetchHourlyForecastForCity(city, { ignoreCache: true, resolution: targetResolution })
.then((data) => {
@@ -102,6 +102,10 @@ export async function runTests() {
chartLogicSource.includes("primeCityDetailCache"),
"visible terminal chart detail fetches should be coalesced into one batch request and prime the shared chart cache",
);
assert(
chartLogicSource.includes("CITY_DETAIL_BATCH_WINDOW_MS = 100"),
"visible terminal chart detail fetches should use a wide enough batch window to coalesce cards mounted across adjacent frames",
);
assert(
chartLogicSource.includes("partial?: boolean") &&
chartLogicSource.includes("missing?: string[]"),
@@ -198,8 +198,9 @@ export function runTests() {
assert(
foregroundRefreshBlock.includes("ignoreCache: true") &&
foregroundRefreshBlock.includes("fetchHourlyForecastForCity") &&
foregroundRefreshBlock.includes("FOREGROUND_FULL_DETAIL_REFRESH_DEDUP_MS") &&
!foregroundRefreshBlock.includes("setIsHourlyLoading(true)"),
"foreground resume refresh should update full detail immediately in the background without showing the loading overlay",
"foreground resume refresh should update full detail in the background without showing the loading overlay or refetching fresh detail",
);
assert(
!chart.includes("/api/city/${encodeURIComponent(city)}/summary"),
@@ -988,7 +988,7 @@ type CityDetailBatchQueue = {
timer: ReturnType<typeof setTimeout> | null;
};
const CITY_DETAIL_BATCH_WINDOW_MS = 25;
const CITY_DETAIL_BATCH_WINDOW_MS = 100;
const CITY_DETAIL_BATCH_MAX_CITIES = 12;
const _cityDetailBatchQueues = new Map<string, CityDetailBatchQueue>();