diff --git a/backend-api/__tests__/readinessWarning.test.js b/backend-api/__tests__/readinessWarning.test.js index 989b159..8ef0d70 100644 --- a/backend-api/__tests__/readinessWarning.test.js +++ b/backend-api/__tests__/readinessWarning.test.js @@ -1,4 +1,4 @@ -const { buildReadinessWarningDetail, buildReadinessWarningMetadata } = require("../../workers/provisioner/readinessWarning"); +const { buildReadinessWarningDetail, buildReadinessWarningMetadata, buildReadinessWarningState } = require("../../workers/provisioner/readinessWarning"); describe("buildReadinessWarningDetail", () => { it("formats a runtime-only readiness warning", () => { @@ -78,3 +78,40 @@ describe("buildReadinessWarningMetadata", () => { }); }); }); + +describe("buildReadinessWarningState", () => { + it("builds deterministic warning state transitions and event payloads", () => { + const readiness = { + runtime: { + ok: false, + url: "http://agent.internal:9090/health", + error: "connection refused", + }, + gateway: { + ok: false, + url: "http://host.docker.internal:19123/", + error: "timeout after 5000ms", + }, + }; + + expect(buildReadinessWarningState({ + agentId: "agent-123", + name: "Nora QA", + host: "agent.internal", + readiness, + })).toEqual({ + agentStatus: "warning", + deploymentStatus: "warning", + event: { + type: "agent_runtime_warning", + message: "Agent \"Nora QA\" deployed with readiness warning: runtime unavailable at http://agent.internal:9090/health (connection refused); gateway unavailable at http://host.docker.internal:19123/ (timeout after 5000ms)", + metadata: { + agentId: "agent-123", + host: "agent.internal", + detail: "runtime unavailable at http://agent.internal:9090/health (connection refused); gateway unavailable at http://host.docker.internal:19123/ (timeout after 5000ms)", + readiness, + }, + }, + }); + }); +}); diff --git a/workers/provisioner/readinessWarning.js b/workers/provisioner/readinessWarning.js index 7821a9d..7150d0f 100644 --- a/workers/provisioner/readinessWarning.js +++ b/workers/provisioner/readinessWarning.js @@ -25,4 +25,17 @@ function buildReadinessWarningMetadata({ agentId, host, readiness }) { }; } -module.exports = { buildReadinessWarningDetail, buildReadinessWarningMetadata }; +function buildReadinessWarningState({ agentId, name, host, readiness }) { + const metadata = buildReadinessWarningMetadata({ agentId, host, readiness }); + return { + agentStatus: 'warning', + deploymentStatus: 'warning', + event: { + type: 'agent_runtime_warning', + message: `Agent "${name}" deployed with readiness warning: ${metadata.detail}`, + metadata, + }, + }; +} + +module.exports = { buildReadinessWarningDetail, buildReadinessWarningMetadata, buildReadinessWarningState }; diff --git a/workers/provisioner/worker.js b/workers/provisioner/worker.js index 59bbc96..a491d8e 100644 --- a/workers/provisioner/worker.js +++ b/workers/provisioner/worker.js @@ -3,7 +3,7 @@ const IORedis = require('ioredis'); const { Pool } = require('pg'); const { agentRuntimeUrl } = require('../../agent-runtime/lib/contracts'); const { waitForAgentReadiness } = require('./healthChecks'); -const { buildReadinessWarningDetail, buildReadinessWarningMetadata } = require('./readinessWarning'); +const { buildReadinessWarningDetail, buildReadinessWarningState } = require('./readinessWarning'); // ── Connections ────────────────────────────────────────── const connection = new IORedis({ @@ -385,12 +385,13 @@ const worker = new Worker('deployments', async (job) => { }); if (!readiness.ok) { const detail = buildReadinessWarningDetail(readiness); + const warningState = buildReadinessWarningState({ agentId: id, name, host, readiness }); console.warn(`[provisioner] Readiness check failed for agent ${id}: ${detail}`); - await db.query("UPDATE agents SET status = 'warning' WHERE id = $1", [id]); - await db.query("UPDATE deployments SET status = 'warning' WHERE agent_id = $1", [id]); + await db.query(`UPDATE agents SET status = '${warningState.agentStatus}' WHERE id = $1`, [id]); + await db.query(`UPDATE deployments SET status = '${warningState.deploymentStatus}' WHERE agent_id = $1`, [id]); await db.query( "INSERT INTO events(type, message, metadata) VALUES($1, $2, $3)", - ['agent_runtime_warning', `Agent "${name}" deployed with readiness warning: ${detail}`, JSON.stringify(buildReadinessWarningMetadata({ agentId: id, host, readiness }))] + [warningState.event.type, warningState.event.message, JSON.stringify(warningState.event.metadata)] ); }