Skip to content

feat(health): the UI can now report that it cannot do its job - #334

Merged
GeiserX merged 1 commit into
mainfrom
feat/ui-health-endpoint
Aug 13, 2026
Merged

feat(health): the UI can now report that it cannot do its job#334
GeiserX merged 1 commit into
mainfrom
feat/ui-health-endpoint

Conversation

@GeiserX

@GeiserX GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Why

The UI half of the healthcheck audit. Its container healthcheck was a TCP connect — completed by the kernel's listen backlog while uvicorn is wedged, the scheduler is dead or the database is unreadable — and docs/guides/prometheus-metrics.md claimed both images verify "the app inside is actually answering", which after #330 was only true of the worker. Separately, the bell's "All collectors healthy" renders from a latch that can never go false once set: after a scheduler death, every signal stays affirmatively green — green worker dots (a frozen status column), a healthy bell, week-old balances that look identical to fresh ones — indefinitely.

What

  • GET /api/health (unauthenticated — the Docker healthcheck has no credentials; registered in the anonymous-rejection test's PUBLIC list with its reason). Answers three concrete operational questions and 503s with fixed state names: scheduler stopped, no collection completed in N minutes (2.5× the interval — one slow run plus one missed slot of flap resistance), database unreadable. Exception text never reaches the unauthenticated body, and there is a test pinning that.
  • The staleness stamp measures completion, not success — stamped in the collection finally. A wedged collection lock freezes it, because the skip path returns before the finally: the wedge that "Collection already in progress, skipping" used to disguise as routine is now exactly what this detects.
  • Dockerfile healthcheck asks the endpoint via http.client with an explicit 200 check (urlopen honors http_proxy with no localhost exemption — the worker-side lesson from fix(worker): report unhealthy when the worker cannot reach the UI #330's review). Verified to parse intact in a real Docker build.
  • The bell stops lying: when the server-computed collection_stale flag is set it renders "No collection in N minutes — status unknown" instead of affirming health from the permanent latch.

Testing

  • 9 new tests with negative controls: healthy + unauthenticated exact shape, each degradation cause, no-secrets-in-body, completed run advances the stamp vs lock-skip does not, fresh vs frozen staleness contract.
  • Full suite 4673 passed, coverage 96.56%; ruff + format + node --check clean; the anonymous-rejection sweep (87 routes) passes with the one documented exemption.

Summary by CodeRabbit

  • New Features

    • Added an unauthenticated health endpoint reporting scheduler, collection, and database status.
    • Health checks now return clear degraded status details when services are unavailable.
    • Collector alerts now show collection age and identify stale results.
  • Bug Fixes

    • The interface no longer reports all collectors as healthy when results are outdated.
    • Container health monitoring now verifies a successful HTTP health response.

The UI half of the healthcheck audit. The container healthcheck was a
TCP connect — completed by the kernel's listen backlog while uvicorn is
wedged, the scheduler is dead or the database is unreadable — and the
docs claimed both images verify 'the app inside is actually answering',
which was only true of the worker after #330. Meanwhile the bell's 'All
collectors healthy' renders from a latch that can never go false once
set, so a dead scheduler left every signal affirmatively green with
week-old numbers underneath, indefinitely.

- GET /api/health (unauthenticated — the Docker healthcheck asks it,
  and it is registered in the anonymous-rejection test's PUBLIC list
  with its reason): 503 + fixed problem names when the scheduler is
  stopped, when no collection has COMPLETED within 2.5x the interval,
  or when the database cannot be read. The stamp measures completion,
  not success — and a wedged collection lock freezes it, because the
  skip path returns before the finally: the wedge the skip line used
  to disguise as routine is now the thing this detects. Reason strings
  are fixed state names; exception text never reaches the response.
- Dockerfile healthcheck asks that endpoint via http.client (urlopen
  honors http_proxy with no localhost exemption — the worker lesson),
  with an explicit 200 check. Verified to parse intact in a real
  docker build.
- The bell goes 'No collection in N minutes — status unknown' when the
  server-computed staleness flag is set, instead of affirming health
  from the permanent latch.

9 new tests incl. negative controls (fresh stamp healthy, lock-skip
does not advance the stamp, no exception text in the unauthenticated
body). Full suite 4673 passed, coverage 96.56%.
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d9b639b-8c20-425b-a6a6-f12240d93060

📥 Commits

Reviewing files that changed from the base of the PR and between ae8fd20 and ed24e17.

📒 Files selected for processing (5)
  • Dockerfile
  • app/main.py
  • app/static/js/app.js
  • tests/test_every_route_rejects_anonymous.py
  • tests/test_ui_health_endpoint.py

📝 Walkthrough

Walkthrough

The application now exposes unauthenticated health status, tracks collection completion freshness, reports stale collector data in the UI, and uses the health endpoint for Docker health checks.

Changes

Health monitoring and collection freshness

Layer / File(s) Summary
Collection freshness tracking
app/main.py, app/static/js/app.js, tests/test_ui_health_endpoint.py
Collection runs record completion time, collector alerts expose age and staleness, and the UI displays stale collection status.
Health endpoint and access rules
app/main.py, tests/test_ui_health_endpoint.py, tests/test_every_route_rejects_anonymous.py
/api/health checks scheduler state, collection freshness, and database readability. It returns HTTP 503 with degradation details when checks fail.
Docker health probe
Dockerfile
The Docker probe requests /api/health and succeeds only for HTTP 200.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: ⚪ Minimal · up to ed24e

The PR adds explicit UI health reporting, stale-collection detection, and a Docker healthcheck response so failures are surfaced instead of appearing healthy; no actionable merge-blocking risk remains beyond normal checks and review.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the health-reporting feature and reflects the primary UI change in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ui-health-endpoint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.62%. Comparing base (ae8fd20) to head (ed24e17).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #334      +/-   ##
==========================================
+ Coverage   95.58%   95.62%   +0.04%     
==========================================
  Files          51       51              
  Lines        6946     6969      +23     
==========================================
+ Hits         6639     6664      +25     
+ Misses        307      305       -2     
Files with missing lines Coverage Δ
app/main.py 97.91% <100.00%> (+0.13%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX

GeiserX commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX
GeiserX merged commit b9166b8 into main Aug 13, 2026
8 checks passed
@GeiserX
GeiserX deleted the feat/ui-health-endpoint branch August 13, 2026 19:10
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