From d9b1acfe8dd640c621218f88536fde7a54e92d93 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Wed, 4 Nov 2026 14:28:20 -0800 Subject: [PATCH] test(agents): the listener check-in test waits for the write, not a fixed 150 ms The check-in write is fire-and-forget, and the test slept 150 ms before reading the route. In the merge queue on 11-04 that lost the race in two of five runs (the file's first test, while a new AgentEvent index built), dequeuing unrelated PRs. It now waits until the stamp is in the database, up to 5 s, then reads the route once. Polling the route itself trips its rate limit (429). A check-in that never writes still fails. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MDs9DPFVAooJnqCSwrdxVw --- .../agent-states-listener-check-in.test.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/backend/__tests__/service/agent-states-listener-check-in.test.js b/backend/__tests__/service/agent-states-listener-check-in.test.js index 197351ab99..00867baae1 100644 --- a/backend/__tests__/service/agent-states-listener-check-in.test.js +++ b/backend/__tests__/service/agent-states-listener-check-in.test.js @@ -40,8 +40,18 @@ describe('GET /api/pods/:podId/agent-states reads listener check-ins', () => { expect(res.status).toBe(200); return Object.fromEntries(res.body.agents.map((a) => [a.agentName, a])); }; - // The check-in writes are fire-and-forget, so wait for them to land. - const settle = () => new Promise((resolve) => { setTimeout(resolve, 150); }); + // The check-in writes are fire-and-forget, so wait until the stamp is in the + // database, then read the route once. A fixed 150 ms wait failed in the + // merge queue under load (two of five runs on 11-04, the file's first test, + // while a new AgentEvent index built). Polling the route instead runs into + // its rate limit. A write that never lands still fails the route assertion. + const landed = async (model, filter) => { + const deadline = Date.now() + 5000; + while (Date.now() < deadline) { + if (await model.exists(filter)) return; + await new Promise((resolve) => { setTimeout(resolve, 25); }); + } + }; beforeAll(async () => { process.env.JWT_SECRET = SECRET; @@ -66,7 +76,7 @@ describe('GET /api/pods/:podId/agent-states reads listener check-ins', () => { expect((await states())['mcp-only'].state).toBe('never-connected'); recordListenerCheckIn((await User.findOne({ username: 'mcp-only' }))._id, 'h-user'); - await settle(); + await landed(User, { username: 'mcp-only', 'agentRuntimeTokens.lastListenedAt': { $ne: null } }); expect((await states())['mcp-only'].state).toBe('listening'); }); @@ -75,7 +85,7 @@ describe('GET /api/pods/:podId/agent-states reads listener check-ins', () => { expect((await states())['install-only'].state).toBe('never-connected'); recordListenerCheckIn(null, 'h-install'); - await settle(); + await landed(AgentInstallation, { agentName: 'install-only', 'runtimeTokens.lastListenedAt': { $ne: null } }); expect((await states())['install-only'].state).toBe('listening'); }); });