mpackdb
All repositories: gitoria
2.4 KB
import MPackDB from '../src/MPackDB.js';import { rm, writeFile, utimes, stat } from 'fs/promises';import { mkdir } from 'fs/promises';const TEST_DB_PATH = 'db/stale-lock';console.log('--- Stale Lock Recovery Test ---');console.log('A crashed process leaves its lock file behind. Waiters must take it');console.log('over after staleLockTimeout instead of hanging forever.\n');await rm(TEST_DB_PATH, { recursive: true, force: true });await mkdir(TEST_DB_PATH, { recursive: true });// TEST 1: stale lock (old mtime) is removed and the operation proceedsconst lockPath = `${TEST_DB_PATH}/users.lock`;await writeFile(lockPath, '99999'); // pretend PID of a dead processconst old = (Date.now() - 60000) / 1000; // 60s agoawait utimes(lockPath, old, old);const db = new MPackDB(`${TEST_DB_PATH}/users`, { primaryKey: '*id', staleLockTimeout: 1000 });const start = Date.now();const id = await Promise.race([db.insert({ name: 'survivor' }),new Promise(r => setTimeout(() => r('TIMEOUT'), 10000)),]);const took = Date.now() - start;const test1Pass = id !== 'TIMEOUT';console.log(`TEST 1: insert with stale lock present: ${test1Pass ? `succeeded in ${took}ms` : 'TIMED OUT'}`);console.log(` ${test1Pass ? '✓ PASS' : '✗ FAIL — waiter hung on a dead process lock'}\n`);// TEST 2: a FRESH lock is respected (no premature takeover)const lockPath2 = `${TEST_DB_PATH}/users.lock`;await writeFile(lockPath2, String(process.pid));const start2 = Date.now();const insert2 = db.insert({ name: 'patient' });// While the fresh lock exists the insert must wait; release it after 400mslet insert2Done = false;insert2.then(() => insert2Done = true);await new Promise(r => setTimeout(r, 400));const stillWaiting = !insert2Done;await rm(lockPath2, { force: true });const id2 = await Promise.race([insert2,new Promise(r => setTimeout(() => r('TIMEOUT'), 10000)),]);const test2Pass = stillWaiting && id2 !== 'TIMEOUT';console.log(`TEST 2: fresh lock respected (waited: ${stillWaiting}), then acquired in ${Date.now() - start2}ms`);console.log(` ${test2Pass ? '✓ PASS' : '✗ FAIL'}\n`);await db.close();// no lock file left behindconst lockLeft = await stat(lockPath).then(() => true).catch(() => false);console.log(`Lock file cleaned up: ${!lockLeft ? '✓ PASS' : '✗ FAIL'}`);const allPass = test1Pass && test2Pass && !lockLeft;console.log(`\n${allPass ? '✓ All stale lock tests passed!' : '✗ Some stale lock tests FAILED'}`);if (!allPass) throw new Error('stale-lock tests FAILED');
Branches
- mastermain branch
Latest commits
- 87888725release 1.0.7caramboleyo
- c4cdb9b6node: import prefixes (Deno compat) + pre-existing index-state WIPcaramboleyo
- 0afb8f4bupdate now must be a callbackcaramboleyo
- cde73eb4release 1.0.6caramboleyo
- d01dda02add index hints, intersection, boundingBox; remove findByIndexcaramboleyo
- b8ffc1a0release 1.0.5caramboleyo
- d47876a1reimplemented lost features like indexed find and more testscaramboleyo
- 7f08da9afixed insert ignoring model definitioncaramboleyo
- 705774a9added flush before findcaramboleyo
- b4db6391initial commitcaramboleyo