You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pollExternalFeeds in client/src/pages/Tracking.tsx (lines 221–304) runs on a setInterval(..., 2000) and does sequential fetches across all enabled feeds. There is no AbortController, no per-fetch timeout, and no "component still mounted" guard.
setState on unmounted component. After the user navigates away from the Tracking page, the interval is cleared, but any in-flight fetches keep running. When they resolve they call setExternalVehicles on a dead component (React logs a warning; over time this leaks memory too).
Suggested fix
Wrap each fetch with AbortController + a per-request timeout (e.g. 5s).
Store the current sweep's controllers in a ref so the effect cleanup can .abort() them.
Track an alive ref set to true on mount, false on unmount, and short-circuit setExternalVehicles when !alive.current.
Related but distinct from #24 (which is about the third-party CORS proxy and unvalidated localStorage JSON) — this one is specifically about the polling mechanics.
Summary
pollExternalFeedsinclient/src/pages/Tracking.tsx(lines 221–304) runs on asetInterval(..., 2000)and does sequentialfetches across all enabled feeds. There is noAbortController, no per-fetch timeout, and no "component still mounted" guard.Impact
Two concrete failure modes:
Overlapping in-flight requests. If one feed URL (or the third-party proxy from Bug: Tracking page external feed loader uses a hard-coded third-party CORS proxy and reads unvalidated localStorage JSON #24) hangs beyond 2 seconds, the next
setIntervaltick starts a fresh sweep on top of the previous one. Requests accumulate faster than they resolve; the manager and/or the third-party proxy see a slowly growing pileup.setState on unmounted component. After the user navigates away from the Tracking page, the interval is cleared, but any in-flight
fetches keep running. When they resolve they callsetExternalVehicleson a dead component (React logs a warning; over time this leaks memory too).Suggested fix
fetchwithAbortController+ a per-request timeout (e.g. 5s)..abort()them.aliveref set totrueon mount,falseon unmount, and short-circuitsetExternalVehicleswhen!alive.current.Related but distinct from #24 (which is about the third-party CORS proxy and unvalidated localStorage JSON) — this one is specifically about the polling mechanics.