Skip to content

fix: truthful health signal — isHealthy no longer lies during a breaker trip - #292

Merged
eschizoid merged 1 commit into
mainfrom
fix/health-snapshot
Jul 31, 2026
Merged

fix: truthful health signal — isHealthy no longer lies during a breaker trip#292
eschizoid merged 1 commit into
mainfrom
fix/health-snapshot

Conversation

@eschizoid

Copy link
Copy Markdown
Owner

Architecture-pass P0 item #1 (+#16). Bug: Handle.isHealthy() = isRunning() = RUNNING || PAUSED — a tripped circuit breaker pauses the consumer, so liveness probes read healthy during the exact incident the breaker exists for. Root cause was three disconnected health pieces: the controller that knows (zero production callers), the handle that answers (wrong source), and the HTTP server that serves (orphaned — the demo documents HEALTH_HTTP_PORT without ever starting it).

One seam fixes all three: HealthSnapshot (running/paused/sources/breaker/in-flight, with healthy() = running && breaker ≠ OPEN) built by KPipeConsumer.health(), exposed via Handle.health(), consumed by DefaultHandle.isHealthy() and the demo's now-real /health endpoint.

Test: CB integration test now asserts the snapshot during OPEN (running=true, healthy=false, source named). Also labels getPartitionState as the test-observation point it is (finding #16).

… breaker together

Handle.isHealthy() returned consumer.isRunning(), which is RUNNING || PAUSED - so a
tripped circuit breaker (which pauses the consumer) read as HEALTHY during the exact
incident the breaker exists for. Meanwhile ConsumerHealthController computed the real
signal with zero production callers, and HttpHealthServer was an orphan no example
ever started (the demo even documents HEALTH_HTTP_PORT without wiring it).

- New HealthSnapshot record (running, paused, pauseSources, circuitBreaker, inFlight)
  with healthy() = running && breaker != OPEN - the single place the health question
  is answered
- KPipeConsumer.health() builds it from ConsumerHealthController (first production
  caller for circuitBreakerState/isPaused/currentSources)
- Handle.health() added; DefaultHandle.isHealthy() delegates to snapshot.healthy()
- Demo app now starts HttpHealthServer from env, suppliers bound to handle.health() -
  the documented /health endpoint exists for real, and reports breaker state
- getPartitionState labeled as a test observation point (audit finding 16)
- KPipeCircuitBreakerIntegrationTest extended: during OPEN, snapshot must report
  running=true, paused=true, source=CIRCUIT_BREAKER, healthy()=false
@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.22%. Comparing base (5c2a392) to head (a875613).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../java/io/github/eschizoid/kpipe/DefaultHandle.java 50.00% 1 Missing ⚠️
...ithub/eschizoid/kpipe/consumer/HealthSnapshot.java 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #292      +/-   ##
============================================
- Coverage     79.26%   79.22%   -0.05%     
- Complexity     1032     1034       +2     
============================================
  Files            83       84       +1     
  Lines          3560     3567       +7     
  Branches        457      457              
============================================
+ Hits           2822     2826       +4     
- Misses          546      547       +1     
- Partials        192      194       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@eschizoid
eschizoid merged commit e2d7fd6 into main Jul 31, 2026
2 of 4 checks passed
@eschizoid
eschizoid deleted the fix/health-snapshot branch July 31, 2026 05: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