mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 14:37:26 +00:00
fix(openontology): migrate in one transaction, and stop timing out on slow disks (#124)
CI failed on an unrelated PR when "seeds a package and hydrates it back identically" passed vitest's default 5s timeout. The assertions were fine; the suite is I/O bound and the runner was slow. Two changes. migrate() ran every DDL statement through its own client.execute(), so migration 1's ~30 statements each became a separate durable commit and opening a store paid ~30 fsyncs. Batch each migration into one write transaction instead: locally a fresh migration drops from ~8.2ms to ~5.0ms, and the gap widens as fsync gets more expensive. It also closes a real hole -- a crash part-way could previously leave the schema half-applied while schema_migrations recorded the migration as done, because the statements and the bookkeeping insert were not atomic. Then give the package a 30s testTimeout. These suites drive a real file-backed SQLite database, so their wall time is set by the host filesystem, not by our code. The 5s default is tuned for CPU-bound unit tests and leaves no headroom on a contended runner. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d2abd201a6
commit
806e78127c
2 changed files with 30 additions and 7 deletions
|
|
@ -225,13 +225,21 @@ export async function migrate(client: Client): Promise<number> {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (const migration of MIGRATIONS) {
|
for (const migration of MIGRATIONS) {
|
||||||
if (have.has(migration.version)) continue;
|
if (have.has(migration.version)) continue;
|
||||||
for (const statement of migration.statements) {
|
// One transaction per migration, rather than one implicit transaction per
|
||||||
await client.execute(statement);
|
// statement. Migration 1 alone is ~30 DDL statements, so opening a store
|
||||||
}
|
// used to cost ~30 durable commits; on a filesystem with slow fsync that
|
||||||
await client.execute({
|
// dominated the open. It is also safer: a crash part-way can no longer
|
||||||
sql: "INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",
|
// leave the schema half-applied while schema_migrations claims it is done.
|
||||||
args: [migration.version, migration.name, new Date().toISOString()]
|
await client.batch(
|
||||||
});
|
[
|
||||||
|
...migration.statements,
|
||||||
|
{
|
||||||
|
sql: "INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",
|
||||||
|
args: [migration.version, migration.name, new Date().toISOString()] as InArgs
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"write"
|
||||||
|
);
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
|
||||||
15
packages/openontology/vitest.config.ts
Normal file
15
packages/openontology/vitest.config.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
// These suites drive a real file-backed SQLite database through
|
||||||
|
// @libsql/client, so their wall time is set by the host filesystem's
|
||||||
|
// durability cost, not by our code. Locally the whole libsql suite runs in
|
||||||
|
// ~250ms; on a contended CI runner a single seed-and-reopen case has been
|
||||||
|
// seen to pass 5s, which is vitest's default and is tuned for CPU-bound
|
||||||
|
// unit tests. Give the I/O-bound cases enough headroom that a slow disk
|
||||||
|
// reports as slow rather than as a spurious failure.
|
||||||
|
testTimeout: 30_000,
|
||||||
|
hookTimeout: 30_000
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue