Pulse/tests/integration/scripts/exclusive-lock.test.mjs
2026-03-18 16:06:30 +00:00

61 lines
1.7 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import { withExclusiveLock } from '../../../scripts/exclusive-lock.mjs';
test('withExclusiveLock serializes competing callers', async () => {
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'pulse-exclusive-lock-'));
const lockPath = path.join(tempRoot, 'build.lock');
const order = [];
let releaseFirst;
const firstHasLock = new Promise((resolve) => {
releaseFirst = resolve;
});
const first = withExclusiveLock(lockPath, async () => {
order.push('first:start');
await firstHasLock;
order.push('first:end');
});
await new Promise((resolve) => setTimeout(resolve, 50));
const second = withExclusiveLock(lockPath, async () => {
order.push('second:start');
order.push('second:end');
});
await new Promise((resolve) => setTimeout(resolve, 50));
assert.deepEqual(order, ['first:start']);
releaseFirst();
await Promise.all([first, second]);
assert.deepEqual(order, ['first:start', 'first:end', 'second:start', 'second:end']);
});
test('withExclusiveLock removes stale locks left by dead owners', async () => {
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'pulse-exclusive-lock-'));
const lockPath = path.join(tempRoot, 'stale.lock');
await fs.mkdir(lockPath, { recursive: true });
await fs.writeFile(
path.join(lockPath, 'owner.json'),
`${JSON.stringify({ pid: 999999, createdAt: '2026-03-12T00:00:00Z' })}\n`,
'utf8',
);
let acquired = false;
await withExclusiveLock(
lockPath,
async () => {
acquired = true;
},
{ timeoutMs: 1_000, staleAfterMs: 0 },
);
assert.equal(acquired, true);
});