UNPKG

mortice

Version:

Isomorphic read/write lock that works in single processes, node clusters and web workers

79 lines 3.65 kB
import cluster from 'cluster'; import { WORKER_REQUEST_READ_LOCK, WORKER_RELEASE_READ_LOCK, MASTER_GRANT_READ_LOCK, WORKER_REQUEST_WRITE_LOCK, WORKER_RELEASE_WRITE_LOCK, MASTER_GRANT_WRITE_LOCK } from './constants.js'; import { nanoid } from './utils.js'; const handleWorkerLockRequest = (emitter, masterEvent, requestType, releaseType, grantType) => { return (worker, requestEvent) => { if (requestEvent != null && requestEvent.type === requestType) { emitter.dispatchEvent(new MessageEvent(masterEvent, { data: { name: requestEvent.name, handler: async () => { // grant lock to worker worker.send({ type: grantType, name: requestEvent.name, identifier: requestEvent.identifier }); // wait for worker to finish await new Promise((resolve) => { const releaseEventListener = (releaseEvent) => { if (releaseEvent.type === releaseType && releaseEvent.identifier === requestEvent.identifier) { worker.removeListener('message', releaseEventListener); resolve(); } }; worker.on('message', releaseEventListener); }); } } })); } }; }; const makeWorkerLockRequest = (name, requestType, grantType, releaseType) => { return async () => { const id = nanoid(); if (process.send == null) { throw new Error('No send method on process - are we a cluster worker?'); } process.send({ type: requestType, identifier: id, name }); return new Promise((resolve) => { const listener = (event) => { if (event.type === grantType && event.identifier === id) { process.removeListener('message', listener); // grant lock resolve(() => { if (process.send == null) { throw new Error('No send method on process - are we a cluster worker?'); } // release lock process.send({ type: releaseType, identifier: id, name }); }); } }; process.on('message', listener); }); }; }; export default (options) => { if (cluster.isPrimary || options.singleProcess) { const emitter = new EventTarget(); cluster.on('message', handleWorkerLockRequest(emitter, 'requestReadLock', WORKER_REQUEST_READ_LOCK, WORKER_RELEASE_READ_LOCK, MASTER_GRANT_READ_LOCK)); cluster.on('message', handleWorkerLockRequest(emitter, 'requestWriteLock', WORKER_REQUEST_WRITE_LOCK, WORKER_RELEASE_WRITE_LOCK, MASTER_GRANT_WRITE_LOCK)); return emitter; } return { isWorker: true, readLock: (name) => makeWorkerLockRequest(name, WORKER_REQUEST_READ_LOCK, MASTER_GRANT_READ_LOCK, WORKER_RELEASE_READ_LOCK), writeLock: (name) => makeWorkerLockRequest(name, WORKER_REQUEST_WRITE_LOCK, MASTER_GRANT_WRITE_LOCK, WORKER_RELEASE_WRITE_LOCK) }; }; //# sourceMappingURL=node.js.map