Repository navigation
Commit 94cef75
domain:server#3 · os-bill · session_01Utp6CXKK9SECcrtZHzxjTK
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgSeyJbqJn9JhDcpyKRreAni)_
Fixes #30407
Clause-②: no — a served answer comes to match the driver's own health
answer; no accept set changes.
Metadata-protocol: none
## 维护者速读
- 改了什么:数据源「测试连接」现在读取驱动健康检查的返回值;连接成功但健康检查答 false 时,答 `ok: false`
并给出一句说明,不再答成功。
- 为什么改:探测只 await 了 `ping`(即驱动的
`checkHealth()`)却丢掉了它的布尔值,一个只告警不抛错、随后自报不健康的连接会被报成「连接成功」。
- 风险与回滚:只改 `datasource-admin-plugin.ts` 的 probe 一处判断;只有字面量 `false`
才拒,抛错路径与 ping 无返回值的句柄行为不变;回滚即 revert 本 PR。
-
先看:`packages/services/service-datasource/src/datasource-admin-plugin.ts`
的 probe(`health === false` 那一行);其测试文件末尾新增的 describe。
- 两分钟验证:`pnpm --filter @objectstack/service-datasource exec vitest run
src/__tests__/datasource-admin-plugin.test.ts -t "probe reads the health
answer"`,预期 4 条全绿。
- 需要你做的:无,席位落地。
## What changes
`DatasourceAdminServicePlugin.probe` awaited the handle's `ping` (or the
`checkHealth` fallback) and dropped the answer. Both the shared
factory's `toHandle` and `createPrebuiltDriverFactory` map `ping` to the
driver's own `checkHealth()`, which reports an unhealthy connection by
answering `false` rather than throwing, so a connect that resolved and
then reported itself unhealthy answered Test connection `ok: true`.
The probe now keeps that answer and, when it is a literal `false`,
returns `ok: false` with the sentence "The driver connected, but its
health check reported the database as unhealthy, so this connection is
not usable. Check that the database exists and accepts these settings,
then test again." The teardown in `finally` still runs. Only `false`
refuses: `ping` is typed as a promise of `unknown` on the handle
contract, and a host-built handle whose ping answers nothing keeps
answering `ok: true` (the existing `fakeFactory` probe test pins that).
The thrown-error path is unchanged.
**Other callers of the handle's `ping`:** none. `git grep` over
`packages/**` and `ui/**` (non-test) finds the probe as the only reader
of a `DatasourceDriverHandle.ping`. The neighbours read the boolean
already: `ExternalDatasourceService.testConnection` (saved-datasource
Test) checks `await driver.checkHealth()` and answers `ok: false` on
`false`; `engine-lifecycle-health.ts` maps `false` to `healthy: false`.
`packages/runtime/src/turso-driver-factory.ts` and
`prebuilt-driver-factory.ts` are producers of `ping`, not readers.
**Serial hold:** the card was serial after PR #30395 (same package).
Seat 3 lifted the hold at 15:00Z because this diff shares no file with
#30395; #30395 then merged (22f0d65) and `origin/main` is merged into
this branch before opening, so the PR is measured against a tree that
already contains it.
## Tests
New top-level `describe('DatasourceAdminServicePlugin: probe reads the
health answer')` in the existing harness
`src/__tests__/datasource-admin-plugin.test.ts`:
- a stub DRIVER (connect resolves, `checkHealth()` answers `false`)
wrapped through `createPrebuiltDriverFactory`, the producer that mirrors
`toHandle`: `ok: false`, the error names the health check, no
`latencyMs`, and connect / checkHealth / disconnect each ran once;
- a handle carrying only `checkHealth` (no `ping`) answering `false`:
`ok: false`;
- CONTROL: the same stub with `checkHealth()` answering `true`: `ok:
true` with a latency;
- CONTROL: a throwing connect keeps its answer exactly (`{ ok: false,
error: THROWN_MESSAGE }`), health never asked, teardown still ran.
Measured first, on `fa9c0aa2` before any source edit: the two `false`
pins red (`expected true to be false`), both controls green.
Ablation (one, on the committed fix `2cc82972`):
`scripts/ablation-replace.mjs --delete` on the `if (health === false)
return …` line, anchor x1 → x0, blob 9c49cde → ae6fa722; the file run
went `2 failed | 33 passed (35)` (exactly the two `false` pins), then
restored to blob == HEAD with `git diff HEAD` empty. The suite imports
the plugin by relative `src` path, so no `dist` leg applies.
## Acceptance notes
- The card's production path (`resolveSqliteDriver` handing back a
native driver whose `connect()` swallows a code-less error) is latent
after PR #30395, as the triage says; this PR closes the reading for
every driver that warns instead of throwing.
## Verification
All on head `28086960` (the fix `2cc82972` plus a merge of `origin/main`
`8e5fabe5`, which contains PR #30395).
- `pnpm --workspace-concurrency=2 --filter
'@objectstack/service-datasource...' build && pnpm --filter
@objectstack/service-datasource typecheck && pnpm --filter
@objectstack/service-datasource test` under `os-verify-lock.sh`:
`VERDICT command-exit 0`; `Test Files 72 passed (72)`, `Tests 1187
passed (1187)`.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`: 59 derived families, each run and its exit
recorded; `--ran` reconciliation: `59 derived famil(ies) accounted for —
58 run, 1 NOT-MEASURED`.
- 58 exit 0. `check-plugin-teardown-shape.mjs --self-test` first exited
3 on the shallow clone (fixture commit absent); after `git fetch origin
621a487…` it exited 0 (48 cases pass).
- NOT MEASURED: `pnpm check:dual-build-cjs-loads`, reason: exit 3
PREREQUISITE NOT MET, it reads every package's `dist/` and only the
service-datasource closure was built here. CI runs it in `Lint & Repo
Gates`.
- `pnpm --filter @objectstack/spec check:liveness`: exit 0.
- Not run locally, declared to CI: `test:repo` (no file of that project
changed), repo-wide `pnpm lint`, the full farm.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CXKK9SECcrtZHzxjTK)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7a5f73e commit 94cef75
3 files changed
Lines changed: 95 additions & 2 deletions
File tree
- .changeset
- packages/services/service-datasource/src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
855 | 856 | | |
856 | 857 | | |
857 | 858 | | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1016 | 1016 | | |
1017 | 1017 | | |
1018 | 1018 | | |
1019 | | - | |
1020 | | - | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
1021 | 1031 | | |
| 1032 | + | |
1022 | 1033 | | |
1023 | 1034 | | |
1024 | 1035 | | |
| |||
1039 | 1050 | | |
1040 | 1051 | | |
1041 | 1052 | | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
1042 | 1063 | | |
1043 | 1064 | | |
1044 | 1065 | | |
| |||
0 commit comments