UNPKG

mutual-exclusion

Version:

Mutual Exclusion (mutex) object for JavaScript.

83 lines (73 loc) 2.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _errors = require("../errors"); const createMutex = mutexConfigurationInput => { const defaultKey = 'mutex-' + String(Math.random()); const mutexConfiguration = { holdTimeout: 30000, key: defaultKey, waitTimeout: 5000, ...mutexConfigurationInput }; const stores = {}; return { isLocked: (key = defaultKey) => { return Boolean(stores[key]); }, lock: async (routine, lockConfigurationInput = mutexConfiguration) => { const lockConfiguration = { // $FlowFixMe ...mutexConfiguration, ...lockConfigurationInput }; if (!stores[lockConfiguration.key]) { stores[lockConfiguration.key] = { lockCount: 0, locking: Promise.resolve() }; } const store = stores[lockConfiguration.key]; store.lockCount++; let unlockNext; // Creates a promise that is resolved by calling `unlockNext`. // `unlockNext` is result of `willUnlock`. // On first call, `willUnlock` is resolved immediately. // However, afterwards `willLock` is added to `locking`, i.e. // `willLock` locks `locking` until the associated `unlockNext` is called. const willLock = new Promise(resolve => { unlockNext = () => { store.lockCount--; if (store.lockCount === 0) { // eslint-disable-next-line fp/no-delete delete stores[lockConfiguration.key]; } resolve(); }; }); const willUnlock = store.locking.then(() => { return Promise.race([routine(), new Promise((resolve, reject) => { setTimeout(() => { reject(new _errors.HoldTimeoutError('Hold timeout.')); }, lockConfiguration.holdTimeout); })]); }).then(() => { return unlockNext(); }); store.locking = store.locking.then(() => { return willLock; }); const waitTimeout = new Promise((resolve, reject) => { setTimeout(() => { reject(new _errors.WaitTimeoutError('Wait timeout.')); }, lockConfiguration.waitTimeout); }); // Suppress unhandled rejection error. willLock.catch(() => {}); store.locking.catch(() => {}); await Promise.race([willUnlock, waitTimeout]); } }; }; var _default = createMutex; exports.default = _default; //# sourceMappingURL=createMutex.js.map