Record watchdog: corroborate heartbeat staleness against the cache dir before restarting#23463
Conversation
…estarting The record watchdog treats a stale maintainer heartbeat as a dead recorder. But the heartbeat is published by the recording maintainer, so whenever the maintainer lags (e.g. "Unable to keep up with recording segments in cache", blakeblackshear#9661) every camera looks stale at once and all record processes restart together - while recording was actually healthy. The restart churn then produces more, shorter segments, making the maintainer fall further behind. Before restarting on staleness, check the camera's newest cache segment on disk: if a segment is fresher than the staleness threshold, the recorder is demonstrably writing - log a warning, adopt the disk mtime as the heartbeat, and skip the restart. The invalid-segment path is untouched. Validated on a 26-camera production deployment (0.17.1 backport of this change): synchronized mass restarts went from 52/hour to zero, with heartbeat-stale events still occurring ~2/hour but now correctly identified as maintainer lag instead of recording failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
this is incorrect. The stale check not only validates if a camera is writing segments but if they are actually valid. If a camera creates multiple segments that are corrupt, missing video, or other issues then it should still be marked as stale and restarted. |
|
@NickM-27 is right, this is incorrect. There are other issues with the PR:
See the dev docs on the common causes of the "Unable to keep up" messages here. |
Proposed change
The per-camera record watchdog restarts the record ffmpeg when the maintainer heartbeat (
latest_cache_segment_time/ valid-segment time) is older thanrecord_stale_threshold. That heartbeat is published by the recording maintainer, not measured locally — so whenever the maintainer lags behind (theUnable to keep up with recording segments in cacheoverload, #9661-class), every camera goes "stale" at the same moment and every record process is restarted while recording is actually healthy. The synchronized restart cuts segments short at the restart points, giving the maintainer even more files per pass — a self-reinforcing storm.We traced this live on a 26-camera production deployment (0.17.1): fleet-wide record-ffmpeg restarts on a steady cadence (52/hour at peak) while the cameras' newest cache segments on disk were only seconds old at the very moment each watchdog declared them >120s stale. (On 0.17 the effect is severely amplified when a user raises
ffmpeg.retry_interval, which there is also the watchdog lap period; dev's 1s lap already removes that amplifier, but genuine maintainer lag still produces the same false positive on dev.)This change corroborates against reality before restarting on staleness: stat the camera's newest
CACHE_DIRsegment, and if a segment fresher than the staleness threshold exists, the recorder is demonstrably writing — log a warning, adopt the disk mtime as the heartbeat, and skip the restart. Theinvalid_stalepath (an actual invalid-segment report) is deliberately untouched, as are restarts when the cache is genuinely dry.Validation on the production deployment (backport of exactly this check to 0.17.1, running since 2026-06-11): synchronized mass restarts went 52/hour → 0; heartbeat-stale events still occur under load (~2/hour) and are now logged as maintainer lag and skipped, with recordings confirmed continuous on disk throughout; the storm-driven 1-2s segment shredding stopped entirely.
Type of change
Additional information
AI disclosure
AI tool(s) used (e.g., Claude, Copilot, ChatGPT, Cursor): Claude (Claude Code)
How AI was used (e.g., code generation, code review, debugging, documentation): Debugging/diagnosis of the production storm (live tracing, log analysis), drafting the patch, and writing this description.
Extent of AI involvement (e.g., generated entire implementation, assisted with specific functions, suggested fixes): The diagnosis and the patch were produced with AI assistance end-to-end, directed and reviewed by the maintainer of the affected deployment.
Human oversight: The equivalent change has been running on a 26-camera production 0.17.1 deployment since 2026-06-11 with the results described above (mass restarts 52/hour → 0, recordings verified continuous on disk during heartbeat-stale events). The deployment owner reviewed the change and the claims in this PR.
Checklist
enlocale.ruff format frigate)