UNPKG

cross-process-lock

Version:

Cross-process file locking solution with lock-queue

79 lines 3.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LockError = void 0; exports.lock = lock; const tslib_1 = require("tslib"); const logger_1 = require("./logger"); const unlock_1 = require("./unlock"); const node_fs_1 = require("node: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_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (file, options = {}) { 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, node_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, node_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(); }); } //# sourceMappingURL=lock.js.map