test(sse): drive agent-activity durable poll via env seam instead of 2.1s real sleep

Replace the fixed ~2.1s real time-wait in the agent-activity SSE durable
integration test with a bounded FUSION_AGENT_ACTIVITY_POLL_MS env test-seam
(default 2000ms unchanged in production) and poll for the delivered frame.
Removes an FN-5048 real time-wait anti-pattern; production behavior unchanged.
This commit is contained in:
gsxdsm
2026-08-12 17:03:11 -07:00
parent cc1041207c
commit e7d0c37c4e
2 changed files with 36 additions and 6 deletions

View File

@@ -289,6 +289,10 @@ pgDescribe("agent activity SSE durable integration", () => {
afterAll(h.afterAll);
it("delivers an out-of-process-shaped persisted append through the seq tail", async () => {
// FNXC:AgentActivityStream 2026-08-12-00:00: drive the real durable poll fast via its
// bounded env test-seam instead of sleeping a full 2s production cycle (FN-5048).
const priorPollMs = process.env.FUSION_AGENT_ACTIVITY_POLL_MS;
process.env.FUSION_AGENT_ACTIVITY_POLL_MS = "20";
const realCore = await vi.importActual<typeof import("@fusion/core")>("@fusion/core");
getMaxAgentActivitySeq.mockReset().mockImplementation((layer) => realCore.getMaxAgentActivitySeq(layer));
queryAgentActivityEvents.mockReset().mockImplementation((layer, query) => realCore.queryAgentActivityEvents(layer, query));
@@ -311,15 +315,23 @@ pgDescribe("agent activity SSE durable integration", () => {
discriminator: "external-exec-after-connect",
metadata: { runId: "exec-FN-8864-1234567891-abcd" },
});
// No store.emit: the poll is the delivery guarantee for external writers.
await new Promise((resolve) => setTimeout(resolve, 2_100));
const frames = response.write.mock.calls
.map(([frame]) => String(frame))
.filter((frame) => frame.startsWith("event: agent:activity"));
// No store.emit: the poll is the delivery guarantee for external writers. Poll for the
// frame rather than sleeping a fixed cycle so the test tracks real delivery, not a timer.
const agentActivityFrames = () =>
response.write.mock.calls
.map(([frame]) => String(frame))
.filter((frame) => frame.startsWith("event: agent:activity"));
const deadline = Date.now() + 5_000;
while (agentActivityFrames().length < 1 && Date.now() < deadline) {
await new Promise((resolve) => setTimeout(resolve, 20));
}
const frames = agentActivityFrames();
expect(frames).toHaveLength(1);
expect(JSON.parse(frames[0]!.split("data: ")[1]!.trim())).toMatchObject({ seq: "1", taskId: "FN-8864" });
} finally {
response.emit("close");
if (priorPollMs === undefined) delete process.env.FUSION_AGENT_ACTIVITY_POLL_MS;
else process.env.FUSION_AGENT_ACTIVITY_POLL_MS = priorPollMs;
}
});
});

View File

@@ -53,6 +53,24 @@ function sseDebug(message: string): void {
sseLog.debug(message);
}
/*
FNXC:AgentActivityStream 2026-08-12-00:00:
The durable agent-activity seq tail polls every 2s in production — that interval IS the
cross-process delivery guarantee for short-lived out-of-process writers that never emit an
in-process nudge. The PG integration test for that path could only prove delivery by sleeping
a full real poll cycle (~2.1s), which is exactly the kind of real time-wait FN-5048 forbids.
Expose a bounded env test-seam (FUSION_AGENT_ACTIVITY_POLL_MS) so that test can drive the poll
fast without weakening the real 2s default or the delivery contract. Read per-connection so a
test can set it before opening the SSE; clamp to >=10ms so a bad value can never busy-spin.
*/
function resolveAgentActivityPollMs(): number {
const raw = process.env.FUSION_AGENT_ACTIVITY_POLL_MS?.trim();
if (!raw) return 2_000;
const parsed = Number(raw);
if (!Number.isFinite(parsed) || parsed <= 0) return 2_000;
return Math.max(10, Math.floor(parsed));
}
const SSE_CLIENT_ID_MAX_LENGTH = 128;
/*
* FNXC:DashboardSSE 2026-06-23-15:08:
@@ -705,7 +723,7 @@ export function createSSE(
}
void drainAgentActivity();
};
const agentActivityPoll = setInterval(onAgentActivityNudge, 2_000);
const agentActivityPoll = setInterval(onAgentActivityNudge, resolveAgentActivityPollMs());
agentActivityPoll.unref?.();
// --- Event handler definitions ---
const onCreated = (task: unknown) => {