Skip to content

feat(core): expose watcher health endpoint#29

Merged
robinbraemer merged 7 commits into
mainfrom
codex/watch-health
Jul 12, 2026
Merged

feat(core): expose watcher health endpoint#29
robinbraemer merged 7 commits into
mainfrom
codex/watch-health

Conversation

@robinbraemer

@robinbraemer robinbraemer commented Jun 13, 2026

Copy link
Copy Markdown
Member

Intent

Recover the existing minekube/connect-java PR #29 (Expose Connect watcher health) on its same codex/watch-health branch, rebased onto current origin/main, without creating a duplicate PR. Preserve WatchHealthServer intent and public API behavior while retaining current-main libp2p watchless/fallback behavior; health becomes true only for a live accepted watcher open, false during reconnect/stop/error/completion, and remains healthy across the intentionally ignored terminal event when switching to watchless mode. Keep current main's watch-specific OkHttp liveness configuration and metadata behavior. Do not absorb hub#170, broaden unrelated Connect behavior, merge, or release. Validate focused and full Gradle tests/build/checks, then update the same PR #29 using verified force-with-lease semantics against expected remote head ec607b0, and stop when the exact pushed head is conflict-free with green checks.

What Changed

  • Add an optional CONNECT_WATCH_HEALTH_ADDR HTTP server whose /healthz endpoint reports watcher and watchless readiness with 200 or 503 responses.
  • Track health across watcher open, reconnect, error, completion, stop, and synchronized watchless fallback transitions.
  • Stop the health server during platform shutdown and handle Velocity proxy shutdown by disabling Connect cleanly.

Risk Assessment

✅ Low: The prior watcher-health race and Velocity shutdown leak are addressed with bounded synchronization, lifecycle cleanup, and focused regression coverage without materially changing watchless/fallback behavior.

Testing

Verified the public /healthz endpoint across connecting, accepted-open, completion, restart, stop, and watchless-terminal states; focused core/Velocity tests and a fresh full multi-module build/check passed, reviewer-visible API evidence was captured, and generated build outputs were cleaned.

Evidence: End-to-end watcher-health lifecycle

before-start GET /healthz -> 503 unhealthy connecting GET /healthz -> 503 unhealthy watch-open GET /healthz -> 200 ok watch-completed GET /healthz -> 503 unhealthy restarted-open GET /healthz -> 200 ok stopped GET /healthz -> 503 unhealthy watchless-negotiated GET /healthz -> 200 ok watchless-terminal-ignored GET /healthz -> 200 ok

before-start                 GET /healthz -> 503 unhealthy
connecting                   GET /healthz -> 503 unhealthy
watch-open                   GET /healthz -> 200 ok
watch-completed              GET /healthz -> 503 unhealthy
restarted-open               GET /healthz -> 200 ok
stopped                      GET /healthz -> 503 unhealthy
watchless-negotiated         GET /healthz -> 200 ok
watchless-terminal-ignored   GET /healthz -> 200 ok

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

🔧 **Rebase** - 2 issues found → auto-fixed ✅
  • ⚠️ core/src/main/java/com/minekube/connect/module/CommonModule.java - merge conflict rebasing onto origin/codex/watch-health
  • ⚠️ core/src/test/java/com/minekube/connect/module/CommonModuleTest.java - merge conflict rebasing onto origin/codex/watch-health

🔧 Fix applied.
✅ Re-checked - no issues remain.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • 🚨 core/src/main/java/com/minekube/connect/register/WatchHealthServer.java:66 - The HTTP server is never stopped on Velocity because that plugin has no ProxyShutdownEvent handler calling ConnectPlatform.disable(). HttpServer creates its own non-daemon dispatcher thread, so the daemon request executor does not prevent the health endpoint from keeping a normally stopped Velocity JVM alive. Add Velocity shutdown handling that invokes platform.disable().
  • 🚨 core/src/main/java/com/minekube/connect/register/WatcherRegister.java:284 - The terminal-event guard and health update are not atomic. A terminal callback can pass shouldIgnoreTerminalEvent(), then enterWatchlessMode() can mark it ignored, and afterward this callback sets health false permanently while watchless mode remains active. Synchronize watcher transitions/callback state or condition the update on this watcher still being current so ignored terminal events cannot overwrite watchless health.

🔧 Fix: Fix watcher health races and Velocity shutdown lifecycle
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Inspected git diff 26c66a57a39d01e8cea318c0d3a9f9216370b928..386b0fb56d0ff5c36d0adf12f464eb516251ceb5 and the existing watcher/watchless tests
  • ./gradlew :core:test --tests com.minekube.connect.register.WatchHealthServerTest --info
  • ./gradlew :core:test :velocity:test
  • ./gradlew build --rerun-tasks
  • Extracted the observed /healthz responses with rg "GET /healthz" .../watch-health-end-to-end-gradle.log
  • Removed generated build outputs with ./gradlew clean and ./gradlew -p build-logic clean
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Squashed PR #31 after passed CI and paired Moxy/Gate staging validation.
* fix(connect): isolate libp2p runtime from server netty

* Authorize all configured libp2p edge peers

* feat(connect): bootstrap libp2p from watch service

* fix libp2p runtime isolation
@robinbraemer robinbraemer changed the title Expose Connect watcher health feat(core): expose watcher health endpoint Jul 11, 2026
@robinbraemer robinbraemer merged commit 0a3ec0c into main Jul 12, 2026
1 check passed
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