diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d75d3a17..551355954 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,8 +134,9 @@ jobs: port: ${{ job.services.postgres.ports['5432'] }} # One file at a time in a job: files that share CPU starve each other's real-time margins # and migrate.test.ts changes the roles of the whole server. The shards are the parallelism. - # `--test-force-exit` ends a file's process once its tests are done: a failed test that leaves a - # turn parked on a card keeps a timer alive, and its file used to hold the shard to the timeout. + # A file's process ends when nothing holds it: no `--test-force-exit`. Its `process.exit()` can + # deadlock on Node 24.21 joining a V8 compile worker parked until the main thread collects + # garbage (nodejs/node#54918), and held shard 3 to the timeout in about one run in eleven. - run: npm test -w @conexus/server env: TEST_SHARD: ${{ matrix.shard }}/6 diff --git a/apps/server/package.json b/apps/server/package.json index 981f1ca80..e1c99b71e 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -10,7 +10,7 @@ "pretest": "npm run build", "generate": "drizzle-kit generate", "typecheck": "tsc -p tsconfig.json", - "test": "MASTRA_AGENT_THREAD_LEASE_TTL_MS=3000 node --test --test-concurrency=1 --test-force-exit --test-timeout=120000 --test-reporter=../../scripts/test-reporter.ts $(node ../../scripts/server-shards.ts ${TEST_SHARD:-all})" + "test": "MASTRA_AGENT_THREAD_LEASE_TTL_MS=3000 node --test --test-concurrency=1 --test-timeout=120000 --test-reporter=../../scripts/test-reporter.ts $(node ../../scripts/server-shards.ts ${TEST_SHARD:-all})" }, "dependencies": { "@ai-sdk/anthropic": "3.0.133", diff --git a/apps/server/src/builder/agents/code-tool.test.ts b/apps/server/src/builder/agents/code-tool.test.ts index 6b95e9a7c..9bc91e11b 100644 --- a/apps/server/src/builder/agents/code-tool.test.ts +++ b/apps/server/src/builder/agents/code-tool.test.ts @@ -162,7 +162,9 @@ test('o turno parado enquanto o Worker sobe de novo solta a subida: o sinal do t const turn = on.conversation.say('E setembro?') await held.arrived assert.equal((await stopped(on.hub, on.ana, on.url)).statusCode, 200) - const patience = new Promise((resolve) => setTimeout(resolve, 3000, 'STILL_WAITING')) + const patience = new Promise((resolve) => + setTimeout(resolve, 3000, 'STILL_WAITING').unref(), + ) assert.equal(await Promise.race([held.ended, patience]), 'ABORTED', 'the upload kept waiting') assert.equal(endOf(await turn), 'aborted') assert.deepEqual(on.hub.tools.workers(), [], 'the stopped upload left nothing in the namespace') diff --git a/apps/server/src/builder/conversation/conversation-preview.test.ts b/apps/server/src/builder/conversation/conversation-preview.test.ts index 8a3543360..9389abdee 100644 --- a/apps/server/src/builder/conversation/conversation-preview.test.ts +++ b/apps/server/src/builder/conversation/conversation-preview.test.ts @@ -63,7 +63,7 @@ test('a versão não espera o envio: com o envio parado, o fluxo já tem a vers while (!oursIn(before).includes('data-conexus-version')) before.push(await stream.next()) })() await held.arrived - await Promise.race([reading, setTimeout(5_000)]) + await Promise.race([reading, setTimeout(5_000, undefined, { ref: false })]) assert.ok(oursIn(before).includes('data-conexus-version'), 'told while the send is held') assert.ok(oursIn(before).includes('preview:sending')) assert.ok(!oursIn(before).includes('agent_end')) diff --git a/apps/server/src/builder/conversation/test-questions.ts b/apps/server/src/builder/conversation/test-questions.ts index 48a01bf15..453c5043e 100644 --- a/apps/server/src/builder/conversation/test-questions.ts +++ b/apps/server/src/builder/conversation/test-questions.ts @@ -138,9 +138,12 @@ export function invocations(parts: MastraMessagePart[], toolCallId: string) { /** The parked runs in Mastra's database: one run keeps a snapshot of its loop and of its execution. */ export const PARKED = `select distinct run_id from mastra.mastra_workflow_snapshot where snapshot->>'status' = 'suspended'` -/** What `said` resolves to within `ms`, or `undefined`: a stream that says nothing fails the test, not hangs it. */ +/** + * What `said` resolves to within `ms`, or `undefined`: a stream that says nothing fails the test, not + * hangs it. The deadline does not hold the file's process once `said` has answered. + */ export async function within(ms: number, said: Promise): Promise { - return Promise.race([said, sleep(ms).then(() => undefined)]) + return Promise.race([said, sleep(ms, undefined, { ref: false })]) } /** What a call that Mastra closed without an answer reads as: the states of its `tool-invocation` part. */