perf(monitor): throttle selected address lookups

This commit is contained in:
lingniu
2026-07-16 05:52:29 +08:00
parent 3f7619c7cd
commit 4302fc8d45
3 changed files with 121 additions and 7 deletions

View File

@@ -1,4 +1,5 @@
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
import { useEffect, useRef, useState } from 'react';
import { api } from '../../api/client';
import type { MonitorMapResponse, MonitorSummary, MonitorWorkspaceResponse, Page, VehicleRealtimeRow } from '../../api/types';
import { QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
@@ -24,6 +25,67 @@ export const MONITOR_REFRESH = {
export const MONITOR_CACHE = { mapGcTime: 0 } as const;
export const MAX_MONITOR_SEARCH_TERMS = 100;
export const MONITOR_ADDRESS_REFRESH_MS = 60_000;
type MonitorAddressPoint = {
vin: string;
key: string;
longitude: number;
latitude: number;
};
function monitorAddressPoint(vin: string, longitude?: number, latitude?: number): MonitorAddressPoint | undefined {
if (!vin || !Number.isFinite(longitude) || !Number.isFinite(latitude)
|| Math.abs(longitude ?? 0) > 180 || Math.abs(latitude ?? 0) > 90
|| (longitude === 0 && latitude === 0)) return undefined;
const roundedLongitude = Number(longitude!.toFixed(4));
const roundedLatitude = Number(latitude!.toFixed(4));
return {
vin,
key: `${roundedLongitude.toFixed(4)},${roundedLatitude.toFixed(4)}`,
longitude: roundedLongitude,
latitude: roundedLatitude
};
}
function useMonitorAddressPoint(vin: string, longitude?: number, latitude?: number) {
const next = monitorAddressPoint(vin, longitude, latitude);
const [published, setPublished] = useState<MonitorAddressPoint>();
const pendingRef = useRef<MonitorAddressPoint>();
const lastPublishedAtRef = useRef(0);
useEffect(() => {
if (!next) {
pendingRef.current = undefined;
lastPublishedAtRef.current = 0;
setPublished((current) => current === undefined ? current : undefined);
return;
}
if (!published || published.vin !== next.vin) {
pendingRef.current = undefined;
lastPublishedAtRef.current = Date.now();
setPublished(next);
return;
}
if (published.key === next.key) {
pendingRef.current = undefined;
return;
}
pendingRef.current = next;
const elapsed = Date.now() - lastPublishedAtRef.current;
const timer = window.setTimeout(() => {
const pending = pendingRef.current;
if (!pending) return;
pendingRef.current = undefined;
lastPublishedAtRef.current = Date.now();
setPublished(pending);
}, Math.max(0, MONITOR_ADDRESS_REFRESH_MS - elapsed));
return () => window.clearTimeout(timer);
}, [next?.key, next?.vin, published?.key, published?.vin]);
return published;
}
export function parseMonitorSearchTerms(value: string) {
const terms: string[] = [];
@@ -119,8 +181,7 @@ export function useMonitorVehicleCard(vin: string, vehicle?: VehicleRealtimeRow,
const enabled = Boolean(vin);
const longitude = vehicle?.longitude;
const latitude = vehicle?.latitude;
const hasCoordinate = Number.isFinite(longitude) && Number.isFinite(latitude)
&& Math.abs(longitude ?? 0) <= 180 && Math.abs(latitude ?? 0) <= 90;
const addressPoint = useMonitorAddressPoint(vin, longitude, latitude);
const detail = useQuery({
queryKey: ['monitor', 'vehicle-card', 'detail', vin],
@@ -138,12 +199,12 @@ export function useMonitorVehicleCard(vin: string, vehicle?: VehicleRealtimeRow,
gcTime: QUERY_MEMORY.highVolumeGcTime
});
const address = useQuery({
queryKey: ['monitor', 'vehicle-card', 'address', longitude, latitude],
queryKey: ['monitor', 'vehicle-card', 'address', addressPoint?.vin, addressPoint?.key],
queryFn: ({ signal }) => api.reverseGeocode(new URLSearchParams({
longitude: longitude!.toFixed(6),
latitude: latitude!.toFixed(6)
longitude: addressPoint!.longitude.toFixed(4),
latitude: addressPoint!.latitude.toFixed(4)
}), signal),
enabled: enabled && hasCoordinate,
enabled: enabled && addressPoint?.vin === vin,
staleTime: 60 * 60_000,
gcTime: QUERY_MEMORY.highVolumeGcTime
});