1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.Locks = void 0;
- const tslib_1 = require("tslib");
- const defaultStore = typeof window === 'object' && window && typeof window.localStorage === 'object' ? window.localStorage : null;
- let _locks;
- /**
- * Creates a lock manager, which can create exclusive locks across browser tabs.
- * Uses `window.localStorage` by default to lock across tabs.
- *
- * Below example, will wait for 5 seconds to acquire a lock, and then execute
- * the function once lock is acquired and release the lock after function
- * execution. It will fail with `LOCK_TIMEOUT` error if lock is not acquired
- * within the 5 seconds. The lock will acquired for 2 seconds (default 1000ms).
- *
- * ```ts
- * Locks.get().lock('my-lock', 2000, 5000)(async () => {
- * console.log('Lock acquired');
- * });
- * ```
- */
- class Locks {
- constructor(store = defaultStore || {}, now = Date.now, pfx = 'lock-') {
- this.store = store;
- this.now = now;
- this.pfx = pfx;
- }
- acquire(id, ms = 1000) {
- if (ms <= 0)
- return;
- const key = this.pfx + id;
- const lockUntil = this.store[key];
- const now = this.now();
- const isLocked = lockUntil !== undefined && parseInt(lockUntil, 36) > now;
- if (isLocked)
- return;
- const lockUntilNex = (now + ms).toString(36);
- this.store[key] = lockUntilNex;
- const unlock = () => {
- if (this.store[key] === lockUntilNex)
- delete this.store[key];
- };
- return unlock;
- }
- isLocked(id) {
- const key = this.pfx + id;
- const lockUntil = this.store[key];
- if (lockUntil === undefined)
- return false;
- const now = this.now();
- const lockUntilNum = parseInt(lockUntil, 36);
- return lockUntilNum > now;
- }
- lock(id, ms, timeoutMs = 2 * 1000, checkMs = 10) {
- return (fn) => tslib_1.__awaiter(this, void 0, void 0, function* () {
- const timeout = this.now() + timeoutMs;
- let unlock;
- while (!unlock) {
- unlock = this.acquire(id, ms);
- if (unlock)
- break;
- yield new Promise((r) => setTimeout(r, checkMs));
- if (this.now() > timeout)
- throw new Error('LOCK_TIMEOUT');
- }
- try {
- return yield fn();
- }
- finally {
- unlock();
- }
- });
- }
- }
- exports.Locks = Locks;
- Locks.get = () => {
- if (!_locks)
- _locks = new Locks();
- return _locks;
- };
|