From 4b464ad6229a89e7a6197a7852ba41065bc95b6a Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 28 May 2026 18:41:14 +0900 Subject: [PATCH] perf(background-task): reduce output poll latency --- ...background-output.polling-interval.test.ts | 71 +++++++++++++++++++ .../create-background-output.ts | 4 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/tools/background-task/create-background-output.polling-interval.test.ts diff --git a/src/tools/background-task/create-background-output.polling-interval.test.ts b/src/tools/background-task/create-background-output.polling-interval.test.ts new file mode 100644 index 000000000..3075d6ee0 --- /dev/null +++ b/src/tools/background-task/create-background-output.polling-interval.test.ts @@ -0,0 +1,71 @@ +/// +import { describe, expect, test } from "bun:test" +import type { BackgroundTask } from "../../features/background-agent" +import { unsafeTestValue } from "../../../test-support/unsafe-test-value" +import { createBackgroundOutput } from "./create-background-output" +import type { BackgroundOutputClient, BackgroundOutputManager } from "./clients" + +const mockContext = unsafeTestValue["execute"]>[1]>({ + sessionID: "ses_parent", + messageID: "msg_parent", + agent: "sisyphus", + abort: new AbortController().signal, +}) + +function createTask(): BackgroundTask { + return { + id: "bg_fast_poll", + sessionId: "ses_fast_poll", + parentSessionId: "ses_parent", + parentMessageId: "msg_parent", + description: "fast poll", + prompt: "run", + agent: "sisyphus-junior", + status: "running", + } +} + +const client: BackgroundOutputClient = { + session: { + messages: async () => ({ + data: [ + { + info: { role: "assistant", time: "2026-01-01T00:00:00Z" }, + parts: [{ type: "text", text: "completed result" }], + }, + ], + }), + }, +} + +describe("background_output blocking poll interval", () => { + test("#given a short blocking timeout and a task that completes on retry #when fetching output #then it does not sleep for the legacy one second interval", async () => { + // given + let pollCount = 0 + const task = createTask() + const manager: BackgroundOutputManager = { + getTask: (id: string) => { + if (id !== task.id) return undefined + pollCount += 1 + if (pollCount >= 3) { + task.status = "completed" + } + return task + }, + } + const tool = createBackgroundOutput(manager, client) + const startedAt = Date.now() + + // when + const output = await tool.execute({ + task_id: task.id, + block: true, + timeout: 30, + }, mockContext) + + // then + expect(Date.now() - startedAt).toBeLessThan(200) + expect(pollCount).toBeGreaterThanOrEqual(3) + expect(output).toContain("completed result") + }) +}) diff --git a/src/tools/background-task/create-background-output.ts b/src/tools/background-task/create-background-output.ts index b10628e87..9c555b3b7 100644 --- a/src/tools/background-task/create-background-output.ts +++ b/src/tools/background-task/create-background-output.ts @@ -15,6 +15,7 @@ import { recordBackgroundOutputConsumption } from "../../shared/background-outpu const SISYPHUS_JUNIOR_AGENT = getAgentDisplayName("sisyphus-junior") const MISSING_BACKGROUND_TASK_RETRY_DELAY_MS = 100 +const BACKGROUND_OUTPUT_POLL_INTERVAL_MS = 100 type ToolContextWithMetadata = { sessionID: string @@ -140,7 +141,8 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client: if (shouldBlock && isTaskActiveStatus(task.status)) { const startTime = Date.now() while (Date.now() - startTime < timeoutMs) { - await delay(1000) + const remainingMs = timeoutMs - (Date.now() - startTime) + await delay(Math.min(BACKGROUND_OUTPUT_POLL_INTERVAL_MS, Math.max(1, remainingMs))) const currentTask = await getTaskWithMissingRetry(manager, args.task_id) if (!currentTask) {