Repository navigation
test(drivers): a keyset walk by id visits every organization member once, in the driver's order - #29659
Conversation
…m, turso and mongodb (WIP)
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
|
domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS 席位核对ACCEPT ·
|
Requested by Warren · project thread
Fixes #29398
Clause-②: no
Metadata-protocol: none
维护者速读
organization_id+id $gt游标、orderBy id、limit)做 keyset 分页,断言跨页拼起来恰好等于一次不分页的有序读,每个成员恰一次、不混入别的组织。dist),skip-changeset;回滚即 revert。packages/drivers/driver-sql/src/sql-driver-member-keyset-walk-conformance.test.ts(按方言单元跑,含 live Postgres/MySQL),再看driver-memory的同名钉子。pnpm --filter @objectstack/driver-sql exec vitest run src/sql-driver-member-keyset-walk-conformance.test.ts,预期 sqlite 单元 4 个通过、未配置的 live 单元为具名跳过。What changes
Test files only, one per driver package. Each walks a
sys_member-shaped table with the exact query shape ofreadOrganizationMembersToCompletionin@objectstack/core:where { organization_id }then{ organization_id, id: { $gt: after } },orderBy id asc, alimit,fields: ['id', 'user_id'], resuming after each full page's last id. For page sizes 1, 3, 4 (an exact multiple of the 16 rows) and 16, it asserts:orderBy idread, so the order asserted is the driver's own, never JavaScript's;user_idthrough the projection;floor(16 / pageSize) + 1), and a walk that does not end fails instead of hanging.The fixture ids are mixed-case nanoid-alphabet values (
AC Ab9 B-2 a-c aB3 ab b_1 0Zz Z0 z_9 _x -y Mm mN1 n Q-q), no two equal after case folding, plus three ids of another organization.driver-sqlsql-driver-member-keyset-walk-conformance.test.tsDIALECT_CELLScell: sqlite always; live Postgres and MySQL whenOS_TEST_POSTGRES_URL/OS_TEST_MYSQL_URLare set (CI:Temporal Conformance (live PG + MySQL), which runs the whole package)driver-memorymemory-member-keyset-walk-conformance.test.tsdriver-sqlite-wasmsqlite-wasm-member-keyset-walk-conformance.test.tsdriver-tursoturso-member-keyset-walk-conformance.test.tsdriver-mongodbmongodb-member-keyset-walk-conformance.test.tsOS_TEST_MONGODB_MEMORY_SERVER_ENABLED=1); a named skip otherwiseNo changeset: no published file changes. Every driver package publishes only
dist,README.mdandCHANGELOG.md; after a build,member-keysetandorg_walkedhave zero hits under the drivers'dist, and the control (ORDERindriver-sql/dist/index.js) hits. The PR carriesskip-changeset.Why
Item 2 of the card landed as #29545. Item 1 asked for a per-page "each id strictly greater than the last" check in the resolver. That check compares in JavaScript code-point order, but
driver-sqlorders and pages by the database collation, so on an ICUen-USPostgreSQL database it would refuse every correctly ordered page (measured in the report on the card). The seat ruled: no order check inresolve-authz-context.ts; instead, a driver conformance pin that the keyset walk returns every row once, in the driver's order, across page boundaries. That is this PR.resolve-authz-context.tsand every driver are untouched.Tests
Per driver (head 1647e32)
driver-sql, sqlite cell: Tests 4 passed, 2 skipped (the unprovisioned live Postgres and MySQL cells, named).driver-sqlagainst a local PostgreSQL 16, two databases:C.UTF-8and ICUen-US(CREATE DATABASE ... LOCALE_PROVIDER icu ICU_LOCALE 'en-US'). Both: Tests 8 passed, 1 skipped (MySQL). The two databases order the fixture differently, so both a code-point order and a non-code-point order were walked:C.UTF-8(same as JavaScript):-y 0Zz AC Ab9 B-2 Mm Q-q Z0 _x a-c aB3 ab b_1 mN1 n z_9en-US:_x -y 0Zz a-c ab aB3 Ab9 AC b_1 B-2 Mm mN1 n Q-q z_9 Z0driver-memory: Tests 4 passed.driver-sqlite-wasm: Tests 4 passed.driver-turso: Tests 4 passed.driver-mongodb: Tests 4 skipped. NOT MEASURED: no mongod here; the binary download host is refused by this container's proxy (403). No CI job setsOS_TEST_MONGODB_MEMORY_SERVER_ENABLED, so CI does not run it either, as for the package's existing pagination suite.pnpm typecheckfor the five driver packages: exit 0 (head 3784be1; the later commit only mergesmain). The foursrctest files are in their package'stscfile list; the mongodb one is compiled by itscheck:test-typecheckstep (OK).The pin can fail (one-time mutation, no file kept)
A scratch copy of the
driver-sqlpin wrappedfindso that every paged read returned its rows reversed (a driver whose pages are not in its own order). Run on sqlite and on the ICUen-USdatabase, then deleted (git statusclean afterwards):expected [ 'AC', '0Zz', '-y', 'Ab9', …(40) ] to deeply equal [ '-y', '0Zz', 'AC', 'Ab9', …(12) ]); pages of 1 stay green, since a one-row page has no order to lose.en-USPostgres: Tests 6 failed, 2 passed, the same split in both cells.A second scratch copy dropped
orderByfrom every paged read instead. It stayed green on both, becausedriver-sqladds anidorder to a limited read that names none. That is a reading about the driver, not a gap in the pin.Verification
Gates (head 1647e32)
node scripts/pm/dispatch-gates.mjs --commandsderived 49 commands. All 49 were run locally with exit codes captured before any pipe, and all exited 0.--ranreconciled them: 49 derived, 49 run, 0 NOT-MEASURED, 0 UNRUN.check:authz-resolver,check:error-code-casing,check:filter-alias-parity,check:object-def-param-keys,check:tenant-chokepoint. All exited 0.pnpm lintexited 0.check:query-options-erasurecounted the test surface growing 236 to 246, because each pin cast itsfindoptionsas any. The casts were removed (the options type-check as written), and the gate now reads 236, at the ceiling.check-plugin-teardown-shape --self-testneededgit fetch --unshallow(its fixture is pinned to an old commit).Temporal Conformance (live PG + MySQL)skips pull requests and the merge queue, so the live Postgres and MySQL cells of thedriver-sqlpin first run inmain's push battery after merge. The local Postgres readings above stand in for the Postgres half.Acceptance notes
@objectstack/spec/data(PAGINATION_CASESand its siblings). This change does not editpackages/spec, so each driver package carries its own copy of the fixture and the walk. Hoisting them into@objectstack/spec/databeside the pagination cases is a later choice, not a gap.readOrganizationMembersToCompletionchanges its shape, these files do not change with it.utf8mb4_0900_ai_ciis case-insensitive. Two ids equal after case folding would collide on a case-insensitive primary key at insert, so the fixture holds none. That is a different fact from the one pinned here, and it was not measured.Human Minimum
packages/specholds no runtime logic. (No schema touched.)pnpm lintpasses.main, one pull request.skip-changeset.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Card thread session:
session_01JQwxbZ5Pwrph2FpoA9Ucqq, seatdomain:server#4, claim 6590972532.🤖 Generated with Claude Code
https://claude.ai/code/session_01JQwxbZ5Pwrph2FpoA9Ucqq
Generated by Claude Code