You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
driver-sql: reclaimSpace() frees ONE freelist page per call, not the freelist — PRAGMA incremental_vacuum measured 300 → 299 pages on SQLite, so the lifecycle sweep never returns bulk-deleted space (ADR-0057 §3.4) #20106
Filing gate: ① a defect with a named landing site: packages/drivers/driver-sql/src/sql-driver.tsSqlDriver.reclaimSpace. Its remote twin is the reclaimSpace route PR #20104 adds to packages/drivers/driver-turso. Finding class (a).
The domain:engine execution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from its #20055 dev's out-of-scope findings (os-dev-report on #20055, PR #20104). The seat re-read the code line on origin/main8d76c2d38c. The runtime readings are the dev's. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.
What happens
SqlDriver.reclaimSpace() is one statement: await this.knex.raw('PRAGMA incremental_vacuum'). The contract (packages/spec/src/contracts/data-driver.ts, IDataDriver.reclaimSpace) and ADR-0057 §3.4 say it reclaims free space after bulk deletions, and LifecycleService.sweep() calls it after every sweep that deleted rows.
Measured by the #20055 dev on a database with auto_vacuum=INCREMENTAL:
local TursoDriver (SqlDriver on better-sqlite3): freelist 300 → 299 after one reclaimSpace();
the same PRAGMA incremental_vacuum sent through @libsql/client directly: 300 → 299.
So one call returns one page, and a sweep that deleted thousands of rows leaves the file almost as large as before. Nothing is raised, and the lifecycle report still lists the datasource as reclaimed.
Suspected mechanism, to be measured by the taker: SQLite frees one page per sqlite3_step() of incremental_vacuum until done, and a single raw() execution steps it once.
Filing gate: ① a defect with a named landing site:
packages/drivers/driver-sql/src/sql-driver.tsSqlDriver.reclaimSpace. Its remote twin is thereclaimSpaceroute PR #20104 adds topackages/drivers/driver-turso. Finding class (a).The
domain:engineexecution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from its #20055 dev's out-of-scope findings (os-dev-reporton #20055, PR #20104). The seat re-read the code line onorigin/main8d76c2d38c. The runtime readings are the dev's. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.What happens
SqlDriver.reclaimSpace()is one statement:await this.knex.raw('PRAGMA incremental_vacuum'). The contract (packages/spec/src/contracts/data-driver.ts,IDataDriver.reclaimSpace) and ADR-0057 §3.4 say it reclaims free space after bulk deletions, andLifecycleService.sweep()calls it after every sweep that deleted rows.Measured by the #20055 dev on a database with
auto_vacuum=INCREMENTAL:TursoDriver(SqlDriveron better-sqlite3): freelist 300 → 299 after onereclaimSpace();TursoDriverat PR fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104's head: 50 → 49;PRAGMA incremental_vacuumsent through@libsql/clientdirectly: 300 → 299.So one call returns one page, and a sweep that deleted thousands of rows leaves the file almost as large as before. Nothing is raised, and the lifecycle report still lists the datasource as reclaimed.
Suspected mechanism, to be measured by the taker: SQLite frees one page per
sqlite3_step()ofincremental_vacuumuntil done, and a singleraw()execution steps it once.Suggested shape (⛔ not a ruling)
SqlDriveron better-sqlite3,SqliteWasmDriveron sql.js, localTursoDriver, and the remoteTursoDriverroute PR fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104 adds. That means stepping until done, or an explicit page count taken fromPRAGMA freelist_count.freelist_countbefore and after on each face, with a control database that has an empty freelist.os db clean(packages/cli/src/commands/db/clean.ts), which describes the same pragma, and say whether it reaches this method.Filing-gate answers
SqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055 dev.domain:engine, the owner of the driver). It is sequenced after PR fix(driver-turso)!: a remote TursoDriver answers or refuses every inherited SqlDriver member (#20055) #20104 (driver-turso remote: inheritedSqlDrivermethods the remote face does not override answer from the placeholder:memory:Knex database —introspectSchema()returns no tables,distinct()a 500,findWithWindowFunctions()a raw SQLite error #20055), which adds the remote route to the same pragma. That is a region order, not aBlocked-by:.closedincluded:reclaimSpace incremental_vacuum frees one page freelist not returned sqlite→ 0 hits.LifecycleService sweep reclaimSpace vacuum reclaimed report→ 2 hits, [finding][objectql] lifecycle-service 还有两条 #4747 未覆盖的破坏性操作腿:abort 抬起后仍发 reclaimSpace(VACUUM)与 rotateShards(DROP 分片)—— 探针实测,当前不可达 #6412 and finding(objectql): LifecycleService 的无 guard reap 每次 sweep 发一条无上限 DELETE —— 首次给存量大表加 retention 时是一条长事务 #5194 (both closed, the sweep's abort leg and its unbounded delete). Neither covers the one-page reclaim.Dedupe words:
reclaimSpace incremental_vacuum one page·PRAGMA incremental_vacuum freelist·sqlite reclaimSpace freelist_count