cross-process-lock
Version:
Cross-process file locking solution with lock-queue
77 lines • 3.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.lock = exports.LockError = void 0;
const tslib_1 = require("tslib");
const logger_1 = require("./logger");
const unlock_1 = require("./unlock");
const fs_1 = require("fs");
const metadata_1 = require("./metadata");
const DEFAULT_OPTIONS = {
lockTimeout: 12e5,
waitTimeout: 1e4,
};
const INTERVAL = 500;
class LockError extends Error {
}
exports.LockError = LockError;
/**
* Creates a cross-process lock for the given file, for the actual process.
*
* Note, that it will be only a soft-lock, the file will be locked for other
* instances of cross-process-lock, or processes using the same API for locking.
*
* @param file The path of the file to lock.
* @param options The lock options/timeout.
* @returns The function to unlock the file.
*/
function lock(file, options = {}) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
options = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
(0, logger_1.logger)("lock file:%s", file);
(0, logger_1.logger)("lock options:%o", options);
if (!(0, fs_1.existsSync)(file)) {
(0, logger_1.logger)("lock file does not exist");
throw new Error(`The given file (${file}) does not exist!`);
}
const lockTime = Date.now();
const lockFile = `${file}.lock`;
const tryToLock = () => new Promise((resolve, reject) => {
const now = Date.now();
(0, logger_1.logger)("lock now:%d", now);
if (now - lockTime >= options.waitTimeout) {
(0, logger_1.logger)("lock too many tries");
return reject(new LockError(`Couldn't lock file (${file}) in the given timeout (${options.waitTimeout} ms)!`));
}
const done = () => resolve(unlock_1.unlock.bind(null, file));
const next = () => {
(0, logger_1.logger)("lock schedule");
setTimeout(() => {
(0, logger_1.logger)("lock schedule called");
tryToLock().then(done, reject);
}, INTERVAL);
};
let def = Promise.resolve(null);
if ((0, fs_1.existsSync)(lockFile)) {
(0, logger_1.logger)("lock read metadata");
def = (0, metadata_1.readMetadata)(lockFile);
}
def.then((metadata) => {
const actual = Date.now();
const lockedTime = metadata ? actual - metadata.lockTime : -1;
(0, logger_1.logger)("lock metadata:%o", metadata);
(0, logger_1.logger)("lock actual:%d lockedTime:%d", actual, lockedTime);
if (!metadata || metadata.pID === process.pid || lockedTime > options.lockTimeout) {
(0, logger_1.logger)("lock locking");
(0, metadata_1.saveMetadata)(lockFile, lockTime).then(done, next);
}
else {
(0, logger_1.logger)("lock next iteration");
next();
}
}, next);
});
return tryToLock();
});
}
exports.lock = lock;
//# sourceMappingURL=lock.js.map