























@@ -121,6 +121,54 @@ describe("openMemoryDatabaseAtPath readOnly probe", () => {
121121await expectPathMissing(`${orphanBase}-shm`);
122122});
123123124+it("removes aged orphan reindex temp files including the rollback-journal sidecar", async () => {
125+const dbPath = path.join(fixtureRoot, `case-${caseId++}`, "index.sqlite");
126+const dir = path.dirname(dbPath);
127+await fs.mkdir(dir, { recursive: true });
128+const seed = new DatabaseSync(dbPath);
129+seed.exec("CREATE TABLE IF NOT EXISTS meta(key TEXT PRIMARY KEY, value TEXT)");
130+seed.close();
131+132+// NFS-backed stores keep journal_mode=DELETE, so a hard crash during a
133+// reindex leaves a rollback-journal sidecar (.tmp-<uuid>-journal) rather
134+// than -wal/-shm. Cleanup must remove it alongside the temp main file.
135+const orphanBase = `${dbPath}.tmp-22222222-3333-4444-5555-666666666666`;
136+for (const suffix of ["", "-journal"]) {
137+const filePath = `${orphanBase}${suffix}`;
138+await fs.writeFile(filePath, "orphan");
139+const old = new Date(Date.now() - 48 * 60 * 60_000);
140+await fs.utimes(filePath, old, old);
141+}
142+143+const db = openMemoryDatabaseAtPath(dbPath, false);
144+db.close();
145+146+await expectPathMissing(orphanBase);
147+await expectPathMissing(`${orphanBase}-journal`);
148+});
149+150+it("removes a stranded rollback-journal sidecar whose temp main file is already gone", async () => {
151+const dbPath = path.join(fixtureRoot, `case-${caseId++}`, "index.sqlite");
152+const dir = path.dirname(dbPath);
153+await fs.mkdir(dir, { recursive: true });
154+const seed = new DatabaseSync(dbPath);
155+seed.exec("CREATE TABLE IF NOT EXISTS meta(key TEXT PRIMARY KEY, value TEXT)");
156+seed.close();
157+158+// Only the rollback journal survives (its temp main file was already
159+// removed). The discovery set must still recognize the orphan by its
160+// -journal suffix, otherwise it leaks forever.
161+const strandedJournal = `${dbPath}.tmp-33333333-4444-5555-6666-777777777777-journal`;
162+await fs.writeFile(strandedJournal, "stranded journal");
163+const old = new Date(Date.now() - 48 * 60 * 60_000);
164+await fs.utimes(strandedJournal, old, old);
165+166+const db = openMemoryDatabaseAtPath(dbPath, false);
167+db.close();
168+169+await expectPathMissing(strandedJournal);
170+});
171+124172it("keeps young reindex temp files during live database startup", async () => {
125173const dbPath = path.join(fixtureRoot, `case-${caseId++}`, "index.sqlite");
126174const dir = path.dirname(dbPath);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。