diff --git a/internal/cloud/server.ts b/internal/cloud/server.ts index fe85dd61..050d3c0b 100644 --- a/internal/cloud/server.ts +++ b/internal/cloud/server.ts @@ -262,20 +262,24 @@ function ensurePreinstalledHwpodSpec({ workspace }) { export async function buildHealthPayload(options = {}) { const serviceId = CLOUD_API_SERVICE_ID; const env = options.env ?? process.env; + const healthMode = options.healthMode === "live" ? "live" : "readiness"; + const liveProbe = healthMode === "live"; ensureCodeAgentRuntimeBase(env); const metadata = buildMetadataFromEnv(env, { serviceId, fallbackImageRepository: "ghcr.io/pikastech/hwlab-cloud-api" }); - const dbProbe = await buildDbRuntimeReadiness(env, options.dbProbe); + const runtimeStore = options.runtimeStore ?? createConfiguredCloudRuntimeStore({ ...options, env }); + const dbProbe = await buildDbRuntimeReadiness(env, liveProbe ? { ...(options.dbProbe ?? {}), probe: false } : options.dbProbe); const codeAgent = await describeCodeAgentAvailability(env, options); - const runtime = await runtimeReadiness(options.runtimeStore ?? createConfiguredCloudRuntimeStore({ ...options, env })); + const runtime = liveProbe ? runtimeReadinessSnapshot(runtimeStore) : await runtimeReadiness(runtimeStore); const db = applyRuntimeDbReadinessLayers(dbProbe, runtime); const readiness = buildCloudApiReadiness({ db, codeAgent, runtime }); return { serviceId, environment: runtimeEnvironment(env), + healthMode, status: readiness.status, ready: readiness.ready, revision: metadata.revision, @@ -300,11 +304,54 @@ export async function buildHealthPayload(options = {}) { }; } +function runtimeReadinessSnapshot(runtimeStore) { + if (runtimeStore && typeof runtimeStore.summary === "function") { + try { + const summary = runtimeStore.summary(); + return { + ...summary, + readinessFresh: false, + readinessSource: "cached-summary" + }; + } catch (error) { + return { + adapter: "unknown", + durable: false, + ready: false, + status: "degraded", + blocker: "runtime_readiness_snapshot_failed", + reason: error instanceof Error ? error.message : "Runtime readiness snapshot failed", + readinessFresh: false, + readinessSource: "cached-summary", + valuesRedacted: true, + endpointRedacted: true + }; + } + } + return { + adapter: "unknown", + durable: false, + ready: false, + status: "degraded", + blocker: "runtime_readiness_snapshot_unavailable", + reason: "Runtime store does not expose a cached summary for /health/live", + readinessFresh: false, + readinessSource: "cached-summary", + valuesRedacted: true, + endpointRedacted: true + }; +} + async function routeRequest(request, response, options) { const url = new URL(request.url || "/", "http://hwlab-cloud-api.local"); - if (request.method === "GET" && (url.pathname === "/health" || url.pathname === "/health/live")) { - sendJson(response, 200, await buildHealthPayload(options)); + if (request.method === "GET" && url.pathname === "/health/live") { + sendJson(response, 200, await buildHealthPayload({ ...options, healthMode: "live" })); + return; + } + + if (request.method === "GET" && url.pathname === "/health") { + sendJson(response, 200, await buildHealthPayload({ ...options, healthMode: "readiness" })); return; }