process-lock-node v2.0.0
process-lock-node
Simple process locking using Redis.
This module lets you spin up two networked processes and ensure only one of them runs at a time. Lock state is synchronized between processes using Redis.
Installation
npm install process-lock-nodeUsage
Ensure that the REDIS_URL environment variable is set for each process using this library:
REDIS_URL=redis://your-redis-host:6379In your process, intialize a lock by giving it a name and timeout:
const ProcessLock = require('process-lock-node');
const processLock = new ProcessLock('lock_name', 60);Acquire a lock
When the process starts up, attempt to acquire the lock:
function waitForLock() {
processLock.lock((err, owner) => {
if (owner) {
startProcess();
} else {
setTimeout(waitForLock, 60000);
}
});
}Refresh the lock
As long as the process is running, ensure that you refresh the lock. If you do not refresh the lock,
it will expire automatically in timeout seconds, where timeout is the value you passed when initializing
the lock. This is to prevent a process that unexpectly dies from holding the lock indefinitely.
function startProcess() {
setInterval(() => {
processLock.update((err, renewed) => {
if (err || !renewed) {
// Handle the error
}
});
}, 30000);
}The refresh interval must be smaller than the timeout to ensure that we refresh before the lock expires. Setting the refresh interval to half of the timeout is recommended.
Release the lock
When the process exits, clean up the lock so that it can be acquired by another process:
onProcessExit(() => {
processLock.clear((err, cleared) => {
if (err || !cleared) {
// Log the error
}
});
});API reference
new ProcessLock(lockName, timeout)
Construct a process lock.
lockName: stringA name for the lock. Processes that require synchronization should initialize a lock with the samelockName.timeout: numberSeconds from now when an acquired lock will expire and be automatically released.
processLock.lock([callback])
Attempt to acquire a lock.
callback: (err, value: boolean) -> ()A node-style callback that receives the result of attempting to acquire the lock.valueis true if the lock was obtained.
processLock.update([callback])
Attempt to renew a lock.
callback: (err, value: boolean) -> ()A callback that receives the result of attempting to renew the lock.valueis:falseif the lock could not be renewedtrueif it was explicitly renewed.
processLock.clear([force][, callback])
Attempt to release a lock.
force: booleanIf true, force clear the lock even if the current process is not the owner.callback: (err, value: boolean) -> ()A callback that receives the result of attempting to clear the lock.valueis:falseif the lock was not cleared because the current process was not the ownertrueif the lock was cleared *nullif the lock did not exist at all.
processLock.state([callback])
Check the state of a lock.
callback: (err, value: string) -> ()A callback that receives the result of checking a lock's state.valueis"open"or"locked".