Fix Overpass 429: increase debounce, add minimum request interval
- PoiRefresher: Use ref for refresh callback to avoid re-running effect on every category change. Only trigger refresh on category changes, not on mount. - usePois: Bump debounce from 500ms to 1000ms, add 3s minimum interval between actual Overpass requests, increase backoff base to 10s. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c23c325965
commit
c92d4cb4af
2 changed files with 32 additions and 6 deletions
|
|
@ -235,11 +235,14 @@ function NoGoAreaButton({ active, onClick }: { active: boolean; onClick: () => v
|
|||
|
||||
function PoiRefresher({ poiState }: { poiState: ReturnType<typeof usePois> }) {
|
||||
const map = useMap();
|
||||
const refreshRef = useRef(poiState.refresh);
|
||||
refreshRef.current = poiState.refresh;
|
||||
|
||||
useEffect(() => {
|
||||
const refresh = () => {
|
||||
const bounds = map.getBounds();
|
||||
const zoom = map.getZoom();
|
||||
poiState.refresh({
|
||||
refreshRef.current({
|
||||
south: bounds.getSouth(),
|
||||
west: bounds.getWest(),
|
||||
north: bounds.getNorth(),
|
||||
|
|
@ -247,9 +250,25 @@ function PoiRefresher({ poiState }: { poiState: ReturnType<typeof usePois> }) {
|
|||
}, zoom);
|
||||
};
|
||||
map.on("moveend", refresh);
|
||||
refresh();
|
||||
// Don't call refresh() immediately — let moveend trigger it
|
||||
return () => { map.off("moveend", refresh); };
|
||||
}, [map, poiState.refresh]);
|
||||
}, [map]);
|
||||
|
||||
// Trigger refresh when categories change (but not on mount)
|
||||
const prevCategories = useRef(poiState.enabledCategories);
|
||||
useEffect(() => {
|
||||
if (prevCategories.current === poiState.enabledCategories) return;
|
||||
prevCategories.current = poiState.enabledCategories;
|
||||
const bounds = map.getBounds();
|
||||
const zoom = map.getZoom();
|
||||
poiState.refresh({
|
||||
south: bounds.getSouth(),
|
||||
west: bounds.getWest(),
|
||||
north: bounds.getNorth(),
|
||||
east: bounds.getEast(),
|
||||
}, zoom);
|
||||
}, [map, poiState.enabledCategories, poiState.refresh]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ import { getCached, setCached } from "./poi-cache.ts";
|
|||
import { poiCategories } from "./poi-categories.ts";
|
||||
|
||||
const MIN_ZOOM = 12;
|
||||
const DEBOUNCE_MS = 500;
|
||||
const BACKOFF_BASE_MS = 5000;
|
||||
const DEBOUNCE_MS = 1000;
|
||||
const MIN_REQUEST_INTERVAL_MS = 3000;
|
||||
const BACKOFF_BASE_MS = 10000;
|
||||
const MAX_BACKOFF_MS = 60000;
|
||||
|
||||
export type PoiStatus = "idle" | "loading" | "loaded" | "zoom_too_low" | "rate_limited" | "error";
|
||||
|
|
@ -26,6 +27,7 @@ export function usePois(): PoiState {
|
|||
const abortRef = useRef<AbortController | null>(null);
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||
const backoffRef = useRef(0);
|
||||
const lastRequestRef = useRef(0);
|
||||
|
||||
const toggleCategory = useCallback((id: string) => {
|
||||
setEnabledCategories((prev) =>
|
||||
|
|
@ -60,11 +62,16 @@ export function usePois(): PoiState {
|
|||
return;
|
||||
}
|
||||
|
||||
// Calculate delay: debounce + respect minimum interval
|
||||
const sinceLastRequest = Date.now() - lastRequestRef.current;
|
||||
const delay = Math.max(DEBOUNCE_MS, MIN_REQUEST_INTERVAL_MS - sinceLastRequest);
|
||||
|
||||
debounceRef.current = setTimeout(async () => {
|
||||
// Cancel previous request
|
||||
abortRef.current?.abort();
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
lastRequestRef.current = Date.now();
|
||||
|
||||
setStatus("loading");
|
||||
|
||||
|
|
@ -89,7 +96,7 @@ export function usePois(): PoiState {
|
|||
setStatus("error");
|
||||
}
|
||||
}
|
||||
}, DEBOUNCE_MS);
|
||||
}, delay);
|
||||
},
|
||||
[enabledCategories],
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue