fix(health): rename public liveness route to /livez - #257
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR replaces the unauthenticated ChangesLiveness endpoint migration from /health to /livez
🎯 3 (Moderate) | ⏱️ ~20 minutes Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
There was a problem hiding this comment.
Pull request overview
Renames the public unauthenticated liveness endpoint from /health to /livez across the proxy and standalone admin listeners, while keeping the authenticated operator health endpoint at /admin/v1/health. It also shares a common liveness state so /livez can fail during graceful shutdown, and updates docs and tests to match.
Changes:
- Replace public
/healthwith/livezon proxy and admin listeners; add coverage that/healthis now absent. - Introduce shared
LivezStateand mark it shutting down on SIGINT/SIGTERM so liveness can fail during termination. - Update e2e harness readiness checks, docs, and admin OpenAPI to reflect
/livezand retain/admin/v1/health.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/src/harness/app.ts | Updates readiness probe from proxy /health to /livez while keeping admin readiness on /admin/v1/health. |
| tests/e2e/src/cases/health-minimal-e2e.test.ts | Adds e2e regression test asserting /livez works and /health returns 404 on both listeners. |
| docs/testing.md | Updates testing doc to reference /livez as the minimal public probe. |
| docs/api-admin.md | Updates admin API docs to list /livez as the unauthenticated liveness probe. |
| crates/aisix-server/src/main.rs | Threads shared LivezState into shutdown signal handling and into AdminState in standalone mode. |
| crates/aisix-proxy/src/state.rs | Adds livez: Arc<LivezState> to ProxyState and initializes it in constructors. |
| crates/aisix-proxy/src/lib.rs | Replaces router mount /health with /livez and routes to livez_response; adds unit tests for /livez and /health absence. |
| crates/aisix-proxy/src/health.rs | Introduces LivezState + livez_response (plain text “ok”, verbose mode, and shutdown-failure behavior). |
| crates/aisix-etcd/src/supervisor.rs | Updates comments to reference /admin/v1/health instead of /health. |
| crates/aisix-admin/src/state.rs | Adds livez_state to admin state and a builder method to share it with the proxy. |
| crates/aisix-admin/src/openapi.rs | Renames documented public route from /health to /livez and adds schema for plain “ok” response. |
| crates/aisix-admin/src/lib.rs | Replaces router mount /health with /livez (using shared livez_response) and updates tests accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "responses": { | ||
| "200": { | ||
| "description": "OK", | ||
| "content": { | ||
| "text/plain": { | ||
| "schema": { | ||
| "type": "string", | ||
| "enum": ["ok"] | ||
| } | ||
| } | ||
| } |
| pub fn livez_response(livez: &LivezState, verbose: bool) -> Response { | ||
| let mut body = String::new(); | ||
| let mut failed = false; | ||
|
|
||
| body.push_str("[+]ping ok\n"); | ||
| match livez.shutdown_check() { | ||
| Ok(()) => body.push_str("[+]shutdown ok\n"), | ||
| Err(_) => { | ||
| failed = true; | ||
| body.push_str("[-]shutdown failed: reason withheld\n"); | ||
| } | ||
| } |
| pub fn livez_response(livez: &LivezState, verbose: bool) -> Response { | ||
| let mut body = String::new(); | ||
| let mut failed = false; | ||
|
|
||
| body.push_str("[+]ping ok\n"); | ||
| match livez.shutdown_check() { | ||
| Ok(()) => body.push_str("[+]shutdown ok\n"), | ||
| Err(_) => { | ||
| failed = true; | ||
| body.push_str("[-]shutdown failed: reason withheld\n"); |
| "responses": { | ||
| "200": { | ||
| "description": "OK", | ||
| "content": { | ||
| "text/plain": { | ||
| "schema": { | ||
| "type": "string", | ||
| "enum": ["ok"] | ||
| } | ||
| } | ||
| } |
| app.signal("SIGTERM"); | ||
|
|
||
| const deadline = Date.now() + 3000; | ||
| let observedUnhealthy = false; | ||
| while (Date.now() < deadline) { | ||
| try { | ||
| const res = await harnessRequest(`${app.proxyUrl}/livez`, { method: "GET" }); | ||
| if (res.statusCode !== 200) { | ||
| observedUnhealthy = true; | ||
| await res.body.dump(); | ||
| break; | ||
| } | ||
| await res.body.dump(); | ||
| } catch { | ||
| observedUnhealthy = true; | ||
| break; | ||
| } | ||
| await new Promise((r) => setTimeout(r, 50)); | ||
| } | ||
|
|
||
| expect(observedUnhealthy).toBe(true); | ||
| app = undefined; |
| } | ||
|
|
||
| livez_state.mark_shutting_down(); | ||
| tokio::time::sleep(std::time::Duration::from_secs(1)).await; |
- quickstart/self-hosted: document the /livez liveness route and plain-text body (per #257); add Cleanup - quickstart/openai-sdk: switch to .mjs so \`node\` runs the example without a TypeScript loader - quickstart/first-model-first-key-first-request: add production-credentials warning, 401/403 verification step using the real proxy error envelope, Cleanup, and a per-provider api_base callout - integration/openai-compatible-api: add mermaid diagram of the request path; route list reflects the /livez rename - integration/errors-and-retries: replace placeholder error.type strings with the real ProxyError mapping; add 413 RequestTooLarge row; note the admin {error_msg} envelope distinction - configuration/provider-keys: warn about plaintext secret storage; replace the inaccurate OpenAI api_base normalization claim with a per-provider truth table (refs #270) - operations/health-checks: rewrite for the /livez liveness contract plus the /admin/v1/health per-model shape (per #256 + #257) - reference/proxy-api-reference: /livez instead of /health in the route list - tutorials/build-a-virtual-model-with-failover: rewrite end-to-end against routing-strategies-e2e (deliberately break primary, observe cooldown) - tutorials/enable-response-caching: rewrite against cache-policy-e2e (x-aisix-cache miss then hit, different prompt misses again) - tutorials/add-keyword-guardrails: rewrite against guardrail-keyword-e2e (422 content_filter; no-leak message contract per #203) - tutorials/openai-client-to-anthropic-upstream: rewrite against anthropic-upstream-e2e; document bare-host api_base for Anthropic Every command, field, header, and error code was cross-checked against the relevant crate or e2e test on this branch. No mock data; nothing speculative.
- quickstart/self-hosted: document the /livez liveness route and plain-text body (per #257); add Cleanup - quickstart/openai-sdk: switch to .mjs so \`node\` runs the example without a TypeScript loader - quickstart/first-model-first-key-first-request: add production-credentials warning, 401/403 verification step using the real proxy error envelope, Cleanup, and a per-provider api_base callout - integration/openai-compatible-api: add mermaid diagram of the request path; route list reflects the /livez rename - integration/errors-and-retries: replace placeholder error.type strings with the real ProxyError mapping; add 413 RequestTooLarge row; note the admin {error_msg} envelope distinction - configuration/provider-keys: warn about plaintext secret storage; replace the inaccurate OpenAI api_base normalization claim with a per-provider truth table (refs #270) - operations/health-checks: rewrite for the /livez liveness contract plus the /admin/v1/health per-model shape (per #256 + #257) - reference/proxy-api-reference: /livez instead of /health in the route list - tutorials/build-a-virtual-model-with-failover: rewrite end-to-end against routing-strategies-e2e (deliberately break primary, observe cooldown) - tutorials/enable-response-caching: rewrite against cache-policy-e2e (x-aisix-cache miss then hit, different prompt misses again) - tutorials/add-keyword-guardrails: rewrite against guardrail-keyword-e2e (422 content_filter; no-leak message contract per #203) - tutorials/openai-client-to-anthropic-upstream: rewrite against anthropic-upstream-e2e; document bare-host api_base for Anthropic Every command, field, header, and error code was cross-checked against the relevant crate or e2e test on this branch. No mock data; nothing speculative.
Summary
/healthto/livezon both proxy and standalone admin listeners/admin/v1/healthunchanged for authenticated operator health, and update OpenAPI, docs, and e2e coverage to matchSummary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests