feat: add runtime_status and is_ready - #173
Conversation
Adds Client.runtime_status (GET /v1/status), reporting per-component state for http, flight, metrics and opentelemetry, and Client.is_ready (GET /v1/ready) for the boolean case. Neither was reachable from the SDK. /v1/ready answers with text/plain and uses 503 to mean 'not ready', so it needs a raw response rather than send_request's raise_for_status + json decode; adds HttpRequests.send_request_raw for that. ComponentStatus preserves an unrecognized status as a plain string so a status added by a newer runtime does not raise.
There was a problem hiding this comment.
Pull request overview
Adds runtime health/status support to the Python SDK by introducing typed status models and exposing two new Client methods for probing runtime readiness and per-component status.
Changes:
- Add
Client.runtime_status()(wrapsGET /v1/status) returninglist[ConnectionDetails]. - Add
Client.is_ready()(wrapsGET /v1/ready) returningbool, backed by newHttpRequests.send_request_raw(). - Export
ComponentStatusandConnectionDetailsfrom the top-level package and document usage in the README, with unit tests covering the new behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_status.py | Adds unit tests for status parsing and the new Client health methods. |
| tests/test_http.py | Adds unit tests for the new raw HTTP request helper. |
| spicepy/_status.py | Introduces ComponentStatus and ConnectionDetails models for /v1/status. |
| spicepy/_http.py | Adds HttpRequests.send_request_raw() to return a raw Response without raising/JSON decoding. |
| spicepy/_client.py | Adds Client.runtime_status() and Client.is_ready() using the HTTP helpers. |
| spicepy/init.py | Re-exports new status types (ComponentStatus, ConnectionDetails). |
| README.md | Documents runtime health/status usage patterns. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
black --check runs at its default 88-column width, while ruff is configured for 120, so three assertion call sites that satisfied ruff still failed the black gate. Wrapping is mechanical — the arguments are unchanged.
Head branch was pushed to by a user without write access
|
Triaged the red checks on this PR — they had two independent causes, only one of which was mine. Mine, now fixed ( Not mine — these are the repo-wide breakage #176 already fixes, and they fail identically on #155, #159 and the other open PRs:
I deliberately have not duplicated #176’s |
…1/status entries send_request_raw merged the session headers into the dict the caller passed in, so a caller reusing one headers dict across calls silently accumulated the session's headers. Build a merged copy instead; session headers still take precedence, as in send_request. runtime_status() checked that the response was a list but not that each entry was an object, so a non-object entry surfaced as an AttributeError from ConnectionDetails.from_dict rather than a SpiceAIError naming the offending component.
Head branch was pushed to by a user without write access
|
Pushed A test added later in the branch ( Verified locally against the exact versions CI resolves (
The three workflow runs for this push are sitting at Still not mine, and still unchanged: |
|
Status: this PR is Local verification on |
|
Following up on the
Everything this branch is actually responsible for is green: build on all four Python versions across Linux/macOS/Windows, unit, integration, pylint, mypy, black, bandit, and coverage. It remains |
|
Correction to my previous comment: the ruff #176 is green and awaiting review. Merging it turns the |
What
Adds two runtime health methods to
Client:runtime_status()→list[ConnectionDetails], wrappingGET /v1/status. One entryper runtime connection (
http,flight,metrics,opentelemetry) with thatcomponent's endpoint and
ComponentStatus.is_ready()→bool, wrappingGET /v1/ready.ComponentStatusandConnectionDetailsare exported fromspicepy.Why
Neither endpoint was reachable from this SDK, so a Python user waiting for a runtime
to come up — or diagnosing one that came up wrong — had to hand-roll
requestscallsalongside the client they already had configured.
/v1/readycollapses the runtime to one boolean;/v1/statussays which componentis not ready, which is the difference between "not up yet" and "Flight is failing".
Neither requires cluster mode or extra configuration, so both work on a default
spice run.Three details worth a reviewer's eye:
/v1/readyanswerstext/plainand uses503to mean "not ready", so it cannot gothrough
send_request, which callsraise_for_status()and then.json(). This addsHttpRequests.send_request_rawfor endpoints where the status code carries themeaning or the body is not JSON.
is_ready()returnsFalsefor the runtime's503and raisesSpiceAIErrorforanything else, so "not ready" and "could not ask" stay distinct.
ComponentStatus.from_valuereturns an unrecognized status as a plainstrratherthan raising, so a status variant added by a future runtime does not break parsing.
An unknown status is never treated as ready.
Part of aligning runtime health/status coverage across the Spice SDKs.
Verification
make test-unit— 404 passed (up from 379; 25 new tests)make type-check(mypy) — success, no issues in 11 source filesruff checkon the new files — clean; whole-repo error count unchanged fromtrunk(2 pre-existingPLR0917in_client.py, untouched here)ruff format --checkon the new files — cleanpylint— 9.27/10, above the 8.0 gatemake test-integration) — not run; they require a liveruntime, which is not available in this environment.
Note on the 8 remaining
test-unitfailures: they are the pre-existingadbc_driver_managerparameterized-query tests intests/test_main.py, and they failidentically on unmodified
trunkhere. This change adds no new failures.Scoped deliberately to additions only — I avoided running
make format, which with thecurrent
ruff>=0.15.12would reformat 15 files unrelated to this change.