acquireLock
functionAcquires a named lock that only one process on this machine holds at a time, such as one that guards a port, a browser profile, or a script that mustn't run twice. The lock is a jg-fs lock folder in the locks folder, with an owner.json that names the process: its pid, host, nonce, program, folder, start time, and the caller's metadata, never its arguments, which can hold secrets.
With waitSeconds, it waits while a live process holds the lock, checking every 250 ms, and calls onWait once for each new holder; Infinity waits until signal aborts. A lock without a readable owner.json is waited on for up to 16 seconds, because a new owner is still writing it. It fails at once, with jg-fs's LOCK_BUSY and its data.reason, for an owner whose process is gone, one on another host, a takeover in progress, or unexpected files, because waiting can't change them, and with the last reason when the wait runs out. It never takes a lock over by itself: pass the dead owner inspectLock gives as recoverFrom once what it left is checked. An aborted signal rejects with its reason. A lock isn't re-entrant: a process that waits for a lock it already holds waits for itself.
acquireLock(name: string, options?: IAcquireLockOptions): Promise<ILock>Parameters
namestringThe lock's name, such as
acme.app.port-3000.options?IAcquireLockOptionsThe wait, the owner's metadata, the dead owner to take over from, and the folder.
Defaults to
{}.
Returns
Promise<ILock>A promise that resolves to the lock, released with release().
Throws
LOCK_NAME_INVALIDThe lock name must be 1 to 128 lowercase letters, digits, '.', '_' and '-', start with a letter or a digit, not end with '.', and not be a Windows device name.LOCK_OPTIONS_INVALIDThe lock's waitSeconds must be 0 or more, or Infinity.LOCK_ROOT_INVALIDThe locks folder must be an absolute path.LOCK_BUSYThe lock '<path>' is busy.LOCK_ACQUISITION_FAILEDThe lock '<path>' could not be acquired.NOT_A_DIRECTORYThe path '<path>' is not a directory.DIRECTORY_NOT_PRIVATEThe directory '<path>' can be accessed by other users.PATH_NOT_CANONICALThe path '<path>' goes through a symbolic link.
import { acquireLock } from 'jg-locks';
const lock = await acquireLock('acme.app.browser-profile', {
waitSeconds: 60,
onWait: ({ owner }) => console.log(`Waiting for pid ${owner?.pid} to finish`),
});
try {
// use the browser profile
} finally {
await lock.release();
}