OverviewFilesCommitsIssuesDocsReleasesPeers

keet-daemon / test / probe-single-daemon-lock.mjs

53 lines · javascript ref:
// Proves the single-daemon-per-storage guard primitive (index.js): the advisory
// flock on <storage>/keet-daemon.lock must (1) be acquirable by the first daemon,
// (2) REFUSE a second acquirer on the same storage (the stortron --dedicated
// contention that wedged keet-core with "Autobase is closing"), (3) expose the
// holder PID for the refusal message, and (4) auto-release when the holder's fd
// closes (process exit / SIGKILL) so no stale guard blocks a restart.
// fs-native-extensions.tryLock is BSD-flock (verified: same-inode locks conflict
// across fds and release on close), so this is faithful single-process.
import fs from 'bare-fs'
import fsx from 'fs-native-extensions'
import path from 'bare-path'
import os from 'bare-os'

const dir = path.join(os.tmpdir(), 'keet-single-lock-' + Bare.pid)
fs.mkdirSync(dir, { recursive: true })
const lockPath = path.join(dir, 'keet-daemon.lock')

let pass = 0; let fail = 0
const ok = (c, m) => { if (c) { pass++; console.log('  ok  ' + m) } else { fail++; console.log('  FAIL ' + m) } }

// Mirrors the guard in index.js: open 'a+', tryLock, write PID on success.
function acquire () {
  const fd = fs.openSync(lockPath, 'a+')
  if (!fsx.tryLock(fd)) { try { fs.closeSync(fd) } catch {}; return null }
  fs.writeFileSync(lockPath, String(1000 + pass))
  return fd
}

async function main () {
  // 1. First daemon acquires.
  const fd1 = acquire()
  ok(fd1 !== null, '1. first daemon acquires the storage lock')

  // 2. Second daemon on the SAME storage is refused (no wedge).
  const fd2 = acquire()
  ok(fd2 === null, '2. second daemon on same storage is REFUSED')

  // 3. Holder PID is readable for the refusal diagnostic.
  const holder = fs.readFileSync(lockPath, 'utf8').trim()
  ok(holder.length > 0, '3. holder PID readable for the refusal message (got "' + holder + '")')

  // 4. Holder exits (fd close == process death) → lock FREE, no stale guard.
  try { fsx.unlock(fd1) } catch {}; fs.closeSync(fd1)
  const fd3 = acquire()
  ok(fd3 !== null, '4. after holder exits, lock is FREE — a restart is not blocked')
  if (fd3) { try { fsx.unlock(fd3) } catch {}; fs.closeSync(fd3) }

  fs.rmSync(dir, { recursive: true, force: true })
  console.log('\n[probe] pass=' + pass + ' fail=' + fail)
  Bare.exit(fail ? 1 : 0)
}
main().catch((e) => { console.error('[probe] THREW:', e && e.stack ? e.stack : e); Bare.exit(2) })