Repository navigation
feat(server): implement grpc.health.v1.Health/Watch streaming RPC #2569
Copy link
Copy link
Open
Labels
state:staleInactive item at risk of automatic closure.Inactive item at risk of automatic closure.state:triage-neededOpened without agent diagnostics and needs triageOpened without agent diagnostics and needs triage
Description
Problem Statement
Clients that need to observe gateway health changes (e.g., Kaiden, potential Podman Desktop extensions, dashboards, operators) currently have no event-driven mechanism. The only options are:
openshell status -o json— polls the unaryHealthRPC, returnsconnected/disconnectedopenshell gateway info -o json— pollsGetGatewayInfo, returnshealthy/degraded/unhealthy- HTTP
/readyz— poll-based, and disabled by default for local gateways
All of these require polling. For integrations that need to react to gateway state transitions (healthy → degraded, connected → disconnected), polling adds latency and unnecessary load.
The standard gRPC health checking protocol defines a Watch streaming RPC for exactly this purpose.
Proposed Design
Implement the standard grpc.health.v1.Health/Watch server-streaming RPC using tonic-health.
What's already in place:
- The
/grpc.health.path prefix is already in the unauthenticated bypass list (crates/openshell-server/src/auth/oidc.rs:33), so no auth changes are needed. - The
ServiceStatusenum (Healthy,Degraded,Unhealthy) already exists in the proto and SDK. - The
DatabaseHealthMonitorincrates/openshell-server/src/readiness.rsalready maintains atokio::sync::watchchannel with health state — this can drive thetonic-healthreporter.
Implementation outline:
- Add
tonic-healthdependency toopenshell-server. - Register the
grpc.health.v1.Healthservice on the gRPC server alongside the existingOpenShellservice. - Wire the
DatabaseHealthMonitor's watch channel to thetonic-healthreporter so thatWatchstreams reflect actual readiness state (not just "up = healthy"). - Expose the
WatchRPC in the SDK client as a streaming health subscription. - Optionally surface it in the CLI as
openshell status --watchoropenshell status --follow.
Behavior:
Watch("")(empty service) returns overall gateway health.- Status transitions (
Serving→NotServing) are pushed to subscribers when the database health monitor detects a change. - Existing unary
HealthandGetGatewayInfoRPCs remain unchanged.
Alternatives Considered
- Polling
openshell status— works but adds latency (seconds) and CPU cost for tight polling intervals. Acceptable as a fallback but not ideal for reactive integrations. - WebSocket health endpoint — non-standard, requires a separate HTTP upgrade path, harder for gRPC-native clients to consume.
- Custom streaming RPC on the OpenShell service — unnecessary when the standard
grpc.health.v1protocol already exists and tooling supports it.
Agent Investigation
- Confirmed the
grpc.health.v1.Health/WatchRPC is not implemented — notonic-healthdependency exists in the project. - Confirmed the auth bypass for
/grpc.health.is already configured atcrates/openshell-server/src/auth/oidc.rs:33with a test at line 416. - Confirmed the
DatabaseHealthMonitor(crates/openshell-server/src/readiness.rs) already maintains real-time health state viatokio::sync::watchthat could drive the reporter. - The current unary
Healthhandler (crates/openshell-server/src/grpc/mod.rs:224-232) unconditionally returnsHealthy— this proposal would also improve that by connecting it to actual readiness state.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
state:staleInactive item at risk of automatic closure.Inactive item at risk of automatic closure.state:triage-neededOpened without agent diagnostics and needs triageOpened without agent diagnostics and needs triage
Activity
github-actions commentedon Oct 18, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 14 days if there is no further activity. Comment or remove the state:stale label to keep it open.