mutual-exclusion
Version:
Mutual Exclusion (mutex) object for JavaScript.
83 lines (73 loc) • 2.49 kB
JavaScript
;
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