Skip to content

Instantly share code, notes, and snippets.

@andrew--r
Last active January 24, 2024 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrew--r/6e45f2b1661cabec9ea7d0d0bb972e50 to your computer and use it in GitHub Desktop.
Save andrew--r/6e45f2b1661cabec9ea7d0d0bb972e50 to your computer and use it in GitHub Desktop.
node-core-library LockFile error
const {Async} = require('@rushstack/node-core-library');
const {runWithLock} = require('./runWithLock');
function simulateLockedOperation() {
return runWithLock(async () => {
await Async.sleep(250);
});
}
async function run() {
const promises = [];
for (let i = 0; i < 100; i++) {
promises.push(upload());
}
await Promise.all(promises);
}
run();
const {LockFile} = require('@rushstack/node-core-library');
let locked = false;
const currentProcessQueue = [];
/**
* Unfortunately, currently LockFile works only across different processes,
* so we need to handle current process calls manually
*/
function acquireCurrentProcessLock() {
return new Promise((resolve) => {
const release = () => {
locked = false;
const next = currentProcessQueue.shift();
if (next) {
next(release);
}
};
if (locked) {
currentProcessQueue.push(() => {
locked = true;
resolve(release);
});
} else {
locked = true;
resolve(release);
}
});
}
/**
* Runs operation with interprocess lock to ensure
* two operations can’t run simultaneously
*
* @param {() => Promise<unknown>} operation
*/
async function runWithLock(operation, {timeout} = {timeout: 1000 * 60 * 30}) {
const abortController = new AbortController();
const {pid} = process;
const run = async () => {
const release = await acquireCurrentProcessLock();
if (abortController.signal.aborted) {
release();
return;
}
let interProcessLock;
try {
interProcessLock = await LockFile.acquire(__dirname, 'joom-crowdin');
await operation();
} finally {
interProcessLock?.release();
release();
}
};
let timer;
await Promise.race([
run(),
new Promise((_, reject) => {
timer = setTimeout(() => {
abortController.abort();
reject(new Error('joom-crowdin: Lock acquiring timeout reached'));
}, timeout);
if (typeof timer !== 'number' && 'unref' in timer) {
timer.unref();
}
}),
]);
clearTimeout(timer);
}
module.exports = {runWithLock};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment