Skip to content

fix: serve control status from cached snapshot to stop UI probe timeouts#2

Merged
Kyzcreig merged 1 commit into
mainfrom
fix/cached-control-status
Jul 18, 2026
Merged

fix: serve control status from cached snapshot to stop UI probe timeouts#2
Kyzcreig merged 1 commit into
mainfrom
fix/cached-control-status

Conversation

@Kyzcreig

Copy link
Copy Markdown
Owner

Summary

  • serve control-agent status from a deep-copied last-known snapshot instead of synchronously rereading BMC/TrueNAS hardware on every UI probe
  • publish a fresh snapshot after each policy tick and each successful control mutation
  • preserve fail-closed startup behavior by falling back to one real tick before any snapshot exists
  • add concurrency and mutation-cache regression tests

Root cause

ControlService.status() took the same RLock as the policy loop and then performed live BMC/TrueNAS reads. When a policy tick held the lock, the core UI's 2-second control-agent request timed out and rendered intermittent agent_available=false / connection_failed, despite both containers being healthy.

Verification

  • full suite: 44 passed
  • concurrency regression: 25/25 repeated passes
  • ruff check .: pass
  • git diff --check: pass
  • staged secret-shape scan: 0 hits

Live acceptance plan

After merge/image publication:

  1. redeploy the digest-pinned image to the TrueNAS custom app
  2. sample /status across policy ticks and prove zero connection_failed
  3. verify duty/mode readback and thermal override behavior
  4. verify desktop/mobile UI and external-watchdog authority

Root cause: ControlService.status() took the policy RLock and performed
live BMC/TrueNAS reads on every UI probe; when a policy tick held the
lock, the core UI's 2s control-agent request timed out and rendered
intermittent agent_available=false / connection_failed despite healthy
containers (baseline: 12/20 live probes failed at 2s).

- status() now returns a deep-copied last-known snapshot published by
  each policy tick and each successful control mutation
- fail-closed startup preserved: before any snapshot exists, status()
  performs one real tick
- stale-green latch: a failed tick sets status_refresh_failed; cached
  status raises (HTTP 500) instead of serving prior green until the
  next successful tick clears it
- tests: concurrency regression (25x repeat), mutation-cache publish,
  error-latch recovery; suite 46 passed
@Kyzcreig
Kyzcreig merged commit 5778c00 into main Jul 18, 2026
1 check passed
@Kyzcreig
Kyzcreig deleted the fix/cached-control-status branch July 18, 2026 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant