From 704d64ad9e0985a6fd87887ce1193ce3ec66cf13 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 12 Jul 2026 14:55:22 +0000 Subject: [PATCH] Windows install round 4: upgrade PGlite 0.3.16 -> 0.5.4; quarantine partially-initialized data dirs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-diagnosing installer surfaced the real error: PGlite WASM Aborted() on every disk-mode open. Root cause (electric-sql/pglite#794): the round-2 crashed build workers left data\pglite PARTIALLY INITIALIZED, and a poisoned data dir aborts every subsequent open — the absolute-path change couldn't help because the directory itself was corrupt. - @electric-sql/pglite ^0.3.16 -> ^0.5.4: adds NodeFS data-directory locking (prevents the multi-instance corruption class entirely, electric-sql/pglite#892) and fails with a clear message instead of a WASM abort when a dir is unusable. Smoke/tests/build green on 0.5.4 with drizzle 0.45 - Embedded driver now QUARANTINES a non-empty data dir that lacks the markers of a completed initialization (PG_VERSION + postgresql.conf): moved aside as .corrupt- — never deleted — and the engine initializes fresh. Verified end-to-end: a deliberately corrupted dir recovers, real data dirs are untouched Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_014iDzjNAoM7NyKUorQ11wro --- package-lock.json | 8 ++++---- package.json | 4 ++-- src/db/index.ts | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index e742181..d6d762c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.5.0", "license": "Apache-2.0", "dependencies": { - "@electric-sql/pglite": "^0.3.0", + "@electric-sql/pglite": "^0.5.4", "drizzle-orm": "^0.45.2", "exceljs": "^4.4.0", "next": "^15.5.4", @@ -28,9 +28,9 @@ } }, "node_modules/@electric-sql/pglite": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.16.tgz", - "integrity": "sha512-mZkZfOd9OqTMHsK+1cje8OSzfAQcpD7JmILXTl5ahdempjUDdmg4euf1biDex5/LfQIDJ3gvCu6qDgdnDxfJmA==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.5.4.tgz", + "integrity": "sha512-yYZUyyXrHU7tPlCjwZQJ6hIG9DscdCCn7Uk0mYKwC1FeHX286AbcmFveMiRBEak8e9iPupjsoVImN3yJZVed2g==", "license": "Apache-2.0" }, "node_modules/@emnapi/runtime": { diff --git a/package.json b/package.json index d5c3ef3..3ef4866 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.5.0", "private": true, "license": "Apache-2.0", - "description": "CAP Trellis \u2014 open-source client intake, eligibility, case & service management, and CSBG Annual Report 3.0 (OMB 0970-0492) reporting for Community Action Agencies", + "description": "CAP Trellis — open-source client intake, eligibility, case & service management, and CSBG Annual Report 3.0 (OMB 0970-0492) reporting for Community Action Agencies", "repository": { "type": "git", "url": "https://github.com/dchevalier18/csbg-intake.git" @@ -25,7 +25,7 @@ "uuid": "^11.1.1" }, "dependencies": { - "@electric-sql/pglite": "^0.3.0", + "@electric-sql/pglite": "^0.5.4", "drizzle-orm": "^0.45.2", "exceljs": "^4.4.0", "next": "^15.5.4", diff --git a/src/db/index.ts b/src/db/index.ts index cce2163..5efe96a 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -131,7 +131,20 @@ function createPgliteConn(): Conn { // PGlite's own mkdir is NOT recursive — a nested data dir (./data/pglite) // fails with ENOENT unless the parents exist. Create the full path first. if (dir && dir !== "memory") { - fs.mkdirSync(path.resolve(dir), { recursive: true }); + const abs = path.resolve(dir); + fs.mkdirSync(abs, { recursive: true }); + // A data dir a crashed instance left PARTIALLY initialized (e.g. killed + // mid-initdb) aborts every later open. A healthy PGlite dir always has a + // PG_VERSION file — quarantine anything non-empty without one (moved + // aside, never deleted) so the engine can initialize fresh. + const entries = fs.readdirSync(abs); + const healthy = entries.includes("PG_VERSION") && entries.includes("postgresql.conf"); + if (entries.length > 0 && !healthy) { + const quarantine = `${abs}.corrupt-${new Date().toISOString().replace(/[:.]/g, "-")}`; + fs.renameSync(abs, quarantine); + fs.mkdirSync(abs, { recursive: true }); + console.warn(`[db] embedded data dir was partially initialized — moved to ${quarantine} and starting fresh`); + } } // single in-process engine — no advisory lock needed (or available across processes); // embedded mode is for one local server, never for multi-process deployments