From fdd749e1ca52aed4b4300571a556ff6ded829641 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Wed, 9 Sep 2026 09:31:33 -0700 Subject: [PATCH 1/2] test(integration): give TaskManager's workflow waits realistic headroom These four waits are the only ones in the integration suite that override waitForWorkflowCompletion's 5-minute default, at 30s. Each waits on a worker to poll for and complete its tasks, so they are the most sensitive in the suite to server latency, and they lose races on a contended shared server: shard 3/3 has intermittently failed on 'multi worker example', 'Should test a workflow' and two WorkerAdvanced cases across Node 20 and 22 since mid-August. Locally the slowest of them finishes in 3.4s. Raise the budget to 90s and the file's jest timeout to 120s, matching WorkerAdvanced.test.ts. --- src/integration-tests/TaskManager.test.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/integration-tests/TaskManager.test.ts b/src/integration-tests/TaskManager.test.ts index 5ea4db19..5f7f697f 100644 --- a/src/integration-tests/TaskManager.test.ts +++ b/src/integration-tests/TaskManager.test.ts @@ -13,13 +13,17 @@ import { waitForWorkflowCompletion } from "./utils/waitForWorkflowCompletion"; import { describeForOrkesV5 } from "./utils/customJestDescribe"; const BASE_TIME = 1000; +// Every other integration test takes waitForWorkflowCompletion's 5-minute +// default. These four wait on a worker to poll for and finish each task, so +// they need enough room for a slow or contended server; 30s was losing races. +const WF_WAIT_MS = BASE_TIME * 90; describe("TaskManager", () => { const clientPromise = createClientWithRetry(); const workflowsToCleanup: { name: string; version: number }[] = []; const tasksToCleanup: string[] = []; const activeManagers: TaskManager[] = []; - jest.setTimeout(60000); + jest.setTimeout(120000); afterEach(async () => { for (const m of activeManagers) { @@ -136,7 +140,7 @@ describe("TaskManager", () => { const workflowStatus = await waitForWorkflowCompletion( executor, executionId, - BASE_TIME * 30 + WF_WAIT_MS ); expect(workflowStatus.status).toEqual("COMPLETED"); @@ -211,7 +215,7 @@ describe("TaskManager", () => { const workflowStatus = await waitForWorkflowCompletion( executor, status, - BASE_TIME * 30 + WF_WAIT_MS ); expect(workflowStatus.status).toEqual("FAILED"); @@ -283,7 +287,7 @@ describe("TaskManager", () => { const workflowStatus = await waitForWorkflowCompletion( executor, executionId, - BASE_TIME * 30 + WF_WAIT_MS ); expect(workflowStatus.status).toEqual("FAILED"); await manager.stopPolling(); @@ -358,7 +362,7 @@ describe("TaskManager", () => { const workflowStatus = await waitForWorkflowCompletion( executor, executionId, - BASE_TIME * 30 + WF_WAIT_MS ); expect(workflowStatus.status).toEqual("COMPLETED"); From baac9e6c2b6136d36f3c7bf04db6be7e6af41b80 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Thu, 10 Sep 2026 12:16:03 -0700 Subject: [PATCH 2/2] test(integration): let three latency-sensitive suites tolerate a slow server WorkflowExecutor.test.ts: the Return Strategy describe sets a 300s jest timeout, but its beforeAll passed an explicit 30000 override. Registering several workflow definitions against a slow sdkdev outran it, and a dead hook fails every test in the file. Inherit the describe's timeout. LeaseExtension.validation.test.ts: both tests batchPoll with a 200ms long-poll window immediately after startWorkflow, so a queue that takes longer than that to surface the task yields no task and the suite fails on expect(task).toBeDefined(). Widen the window to 5s; the 20s execution and heartbeat behaviour under test is unchanged. Verified against a local Conductor: TaskManager and LeaseExtension pass, and WorkflowExecutor now gets past its hook. --- src/integration-tests/LeaseExtension.validation.test.ts | 7 +++++-- src/integration-tests/WorkflowExecutor.test.ts | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/integration-tests/LeaseExtension.validation.test.ts b/src/integration-tests/LeaseExtension.validation.test.ts index 4704668d..bdd50f75 100644 --- a/src/integration-tests/LeaseExtension.validation.test.ts +++ b/src/integration-tests/LeaseExtension.validation.test.ts @@ -47,6 +47,9 @@ import { cleanupWorkflowsAndTasks } from "./utils/cleanup"; // ─── Timing constants ──────────────────────────────────────────────────────── const RESPONSE_TIMEOUT_SECONDS = 10; // responseTimeoutSeconds on task def const TASK_EXECUTION_MS = 20_000; // worker "works" for 20s (> 10s timeout) +// Long-poll window. The task is polled immediately after startWorkflow, so +// this has to cover the server's queueing latency, not just the network hop. +const POLL_WAIT_MS = 5_000; // Heartbeat fires at 10 * 0.8 = 8s — before the 10s deadline describe("Lease Extension — end-to-end validation", () => { @@ -127,7 +130,7 @@ describe("Lease Extension — end-to-end validation", () => { console.log(`\n▶ Workflow 1 id=${workflowId1} (no heartbeat)`); // Poll the task directly so we control execution - const { data: tasks1 } = await TaskResource.batchPoll({ client, path: { tasktype: taskDefName }, query: { workerid: "val-worker-no-lease", count: 1, timeout: 200 } }); + const { data: tasks1 } = await TaskResource.batchPoll({ client, path: { tasktype: taskDefName }, query: { workerid: "val-worker-no-lease", count: 1, timeout: POLL_WAIT_MS } }); const [task] = tasks1 ?? []; expect(task).toBeDefined(); const taskId1 = task.taskId ?? ""; @@ -172,7 +175,7 @@ describe("Lease Extension — end-to-end validation", () => { const workflowId2 = await executor.startWorkflowByName(wfName, {}, 1); console.log(`\n▶ Workflow 2 id=${workflowId2} (with heartbeat)`); - const { data: tasks2 } = await TaskResource.batchPoll({ client, path: { tasktype: taskDefName }, query: { workerid: "val-worker-with-lease", count: 1, timeout: 200 } }); + const { data: tasks2 } = await TaskResource.batchPoll({ client, path: { tasktype: taskDefName }, query: { workerid: "val-worker-with-lease", count: 1, timeout: POLL_WAIT_MS } }); const [task] = tasks2 ?? []; expect(task).toBeDefined(); const taskId2 = task.taskId ?? ""; diff --git a/src/integration-tests/WorkflowExecutor.test.ts b/src/integration-tests/WorkflowExecutor.test.ts index 1f8bc8de..a12135ae 100644 --- a/src/integration-tests/WorkflowExecutor.test.ts +++ b/src/integration-tests/WorkflowExecutor.test.ts @@ -353,7 +353,9 @@ describe("WorkflowExecutor", () => { // Register all test workflows await registerAllWorkflows(); - }, 30000); + // No explicit hook timeout: inherit the describe's 300s. Registering + // several workflow definitions against a slow server outran 30s. + }); afterEach(async () => { // Clean up executions first