Summary
The reverseGeocode function in asset-service.ts calls OpenStreetMap Nominatim on every fetchAsset invocation when assetLocationCreated is absent. On pages embedding multiple <capture-eye> widgets, this can trigger multiple concurrent Nominatim requests, risking rate-limit violations under Nominatim Usage Policy (max 1 req/sec, no bulk automated queries).
Evidence
Identified during PR #93 review (conversation fe90808c, 2026-03-19). The reviewer explicitly flagged:
如果同一頁面有多個 Capture Eye widget 同時開啟,可能會觸發 rate limit。
While a 3-second AbortController timeout was added to prevent indefinite blocking, there is no request deduplication or rate-limiting mechanism.
Current Behavior
Widget A opens → fetchAsset → reverseGeocode(lat1, lon1) → Nominatim
Widget B opens → fetchAsset → reverseGeocode(lat2, lon2) → Nominatim (concurrent)
Widget C opens → fetchAsset → reverseGeocode(lat3, lon3) → Nominatim (concurrent)
All requests fire simultaneously with no coordination.
Proposed Approach
- In-memory geocoding cache: Cache
(lat, lon) → address results in a module-level Map so repeated coordinates skip the API call entirely
- Request queue with 1 req/sec throttle: Serialize Nominatim requests with a minimum 1-second interval between calls
- Coordinate rounding: Round lat/lon to ~4 decimal places (~11m accuracy) before cache lookup to increase cache hit rate
Impact
- Without fix: Pages with 5+ capture-eye widgets will likely hit Nominatim rate limits, causing geocoding failures and falling back to raw coordinates
- With fix: Compliant with Nominatim usage policy, better UX from cached results, reduced external API dependency
Related
Generated by NREM Mode with Omni
Summary
The
reverseGeocodefunction inasset-service.tscalls OpenStreetMap Nominatim on everyfetchAssetinvocation whenassetLocationCreatedis absent. On pages embedding multiple<capture-eye>widgets, this can trigger multiple concurrent Nominatim requests, risking rate-limit violations under Nominatim Usage Policy (max 1 req/sec, no bulk automated queries).Evidence
Identified during PR #93 review (conversation
fe90808c, 2026-03-19). The reviewer explicitly flagged:While a 3-second
AbortControllertimeout was added to prevent indefinite blocking, there is no request deduplication or rate-limiting mechanism.Current Behavior
All requests fire simultaneously with no coordination.
Proposed Approach
(lat, lon) → addressresults in a module-levelMapso repeated coordinates skip the API call entirelyImpact
Related
Generated by NREM Mode with Omni