From 29ef049465e00402cd5980a1432cbeaeabe496e9 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 01:15:11 +0000 Subject: [PATCH] =?UTF-8?q?fix(service-datasource):=20=E8=A1=A5=20vitest?= =?UTF-8?q?=20=E8=B6=85=E6=97=B6=E9=85=8D=E7=BD=AE=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E7=A9=BA=E6=B4=9E=E5=B9=B6=E5=A4=8D=E6=A0=B8=20pool=20?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E5=B9=B6=E5=8F=91=E9=9A=94=E7=A6=BB=20(#6044?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两条腿: 1. 覆盖空洞:本包此前没有任何 vitest 配置文件,全部用例吃 vitest 默认 5000ms —— #4856 把 testTimeout 逐包落在各包自己的 vitest.config.ts, 结构上覆盖不到没有该文件的本包。补 vitest.config.ts,testTimeout: 60_000 沿用 #4856 的取值不引入新数字,落在配置层使后续新增用例到达即被覆盖。 实测:flaky 用例(datasource-pool-support :122)是全文件第一个走到 `await import('@objectstack/driver-sql')`(knex)的用例,空载 1088ms, 对 5000ms 只有约 4.6 倍余量,队列全量并发下被吃掉即超时 —— 与签名吻合 (仅队列全量构建间歇红,受害 PR 自身全绿)。探针复核:6s 睡眠用例改前 以 "Test timed out in 5000ms" 变红、改后 6.2s 变绿,证明包级配置即生效层。 2. 并发隔离复核(分诊座位明令不许只调超时收尾):逐项排查文件/句柄/共享 状态 —— sqlite 构建落 :memory: 且生产路径不探测、不开连接、native addon 惰性不加载,零文件 I/O;Door-1 各用例 disconnect 销毁空 knex pool; Door-2/3 全部用 per-case fake;无临时文件、无端口、无跨用例可变共享状态。 结论:该红是真实一次性导入成本上的负载方差,不是泄漏,无需修隔离。 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_015a5qkLzpGXhLL2F5gvJ7dD --- .../service-datasource-vitest-testtimeout.md | 32 +++++++++++++++++++ .../service-datasource/vitest.config.ts | 21 ++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 .changeset/service-datasource-vitest-testtimeout.md create mode 100644 packages/services/service-datasource/vitest.config.ts diff --git a/.changeset/service-datasource-vitest-testtimeout.md b/.changeset/service-datasource-vitest-testtimeout.md new file mode 100644 index 0000000000..4ffa8214e5 --- /dev/null +++ b/.changeset/service-datasource-vitest-testtimeout.md @@ -0,0 +1,32 @@ +--- +"@objectstack/service-datasource": patch +--- + +fix(service-datasource): give this package's vitest run a 60s `testTimeout` — close the #4856 coverage hole that let the merge queue evict unrelated PRs (#6044) + +`packages/services/service-datasource` had no `vitest.config.ts` at all, so +every case ran under vitest's **5000ms** default. #4856 fixed this class of +flake by setting per-package timeouts in each package's own `vitest.config.ts` +— a structure that cannot reach a package with no config file to carry it. + +The cases that build a REAL driver pay a one-time `@objectstack/driver-sql` +(knex) import inside the first case that reaches it. In +`datasource-pool-support.test.ts` the pool rejections throw before that import, +so "sqlite WITHOUT a pool still builds exactly as before" is the first case +through it: measured idle it runs ~1.1s while its neighbours run 0-2ms (the +postgres/mysql cases ride the module cache at 31/82ms). ~4.6x headroom against +5000ms holds on a PR branch and not on a merge-queue runner building several +PRs' batches at once — the observed signature: intermittent reds only in queue +full builds, evicting PRs that never touched this package (#5999 twice, #5973 +once, 2026-08-06). + +`testTimeout: 60_000` reuses #4856's value rather than inventing a new number, +set at the config layer so future cases are covered on arrival. Isolation was +reviewed rather than assumed (the #6044 triage forbade a timeout-only closure): +the flaky case builds `:memory:`, unprobed on the production path, never opens +a connection or loads the native addon, and every factory-door case destroys +its knex handle; the boot and wizard doors run on per-case fakes. No temp +files, no ports, no shared mutable state across cases — the red was load +variance on a real one-time import, not a leak. + +No runtime, schema or public API change — test configuration only. diff --git a/packages/services/service-datasource/vitest.config.ts b/packages/services/service-datasource/vitest.config.ts new file mode 100644 index 0000000000..ad9fc793c0 --- /dev/null +++ b/packages/services/service-datasource/vitest.config.ts @@ -0,0 +1,21 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. + +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'node', + // This package had no vitest config at all, so every case ran under + // vitest's 5000ms default — the structural hole #4856 could not cover + // (it set per-package timeouts in each package's own vitest.config.ts, + // and this package had none). The cases that build a REAL driver pay a + // one-time `@objectstack/driver-sql` (knex) import inside the first case + // that reaches it: measured idle that case runs ~1.1s + // (datasource-pool-support "sqlite WITHOUT a pool"), leaving ~4.6x + // headroom that a loaded merge-queue runner eats — the #6044 signature + // (green on every PR branch, intermittently red only in queue full + // builds). 60s reuses #4856's value rather than inventing a new number, + // set at the config layer so future cases are covered on arrival. + testTimeout: 60_000, + }, +});