UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

152 lines 4.79 kB
/** * @module Lock */ import {} from "../../../../execution-context/contracts/_module.js"; import {} from "../../../../lock/contracts/_module.js"; import {} from "../../../../time-span/implementations/_module.js"; import {} from "../../../../utilities/_module.js"; /** * Note the `MemoryLockAdapter` is limited to single process usage and cannot be shared across multiple servers or different processes. * This adapter is meant for easily faking{@link ILockFactory | `ILockFactory`} for testing. * * IMPORT_PATH: `"@daiso-tech/core/lock/memory-lock-adapter"` * @group Adapters */ export class MemoryLockAdapter { map; /** * @example * ```ts * import { MemoryLockAdapter } from "@daiso-tech/core/lock/memory-lock-adapter"; * * const lockAdapter = new MemoryLockAdapter(); * ``` * You can also provide an `Map`. * @example * ```ts * import { MemoryLockAdapter } from "@daiso-tech/core/lock/memory-lock-adapter"; * * const map = new Map<any, any>(); * const lockAdapter = new MemoryLockAdapter(map); * ``` */ constructor(map = new Map()) { this.map = map; } /** * Removes all in-memory lock data. */ async deInit() { for (const [key, lockData] of this.map) { if (lockData.hasExpiration) { clearTimeout(lockData.timeoutId); } this.map.delete(key); } return Promise.resolve(); } async acquire(_context, key, lockId, ttl) { let lock = this.map.get(key); if (lock !== undefined) { return Promise.resolve(lock.owner === lockId); } if (ttl === null) { lock = { owner: lockId, hasExpiration: false, }; this.map.set(key, lock); } else { const timeoutId = setTimeout(() => { this.map.delete(key); }, ttl.toMilliseconds()); lock = { owner: lockId, hasExpiration: true, timeoutId, expiration: ttl.toEndDate(), }; this.map.set(key, lock); } return Promise.resolve(true); } async release(_context, key, lockId) { const lock = this.map.get(key); if (lock === undefined) { return Promise.resolve(false); } if (lock.owner !== lockId) { return Promise.resolve(false); } // Check expiration: if expired, cannot release if (lock.hasExpiration && lock.expiration <= new Date()) { return Promise.resolve(false); } if (lock.hasExpiration) { clearTimeout(lock.timeoutId); } this.map.delete(key); return Promise.resolve(true); } async forceRelease(_context, key) { const lock = this.map.get(key); if (lock === undefined) { return Promise.resolve(false); } // Check expiration: if expired, cannot force release if (lock.hasExpiration && lock.expiration <= new Date()) { return Promise.resolve(false); } if (lock.hasExpiration) { clearTimeout(lock.timeoutId); } this.map.delete(key); return Promise.resolve(true); } async refresh(_context, key, lockId, ttl) { const lock = this.map.get(key); if (lock === undefined) { return Promise.resolve(false); } if (lock.owner !== lockId) { return Promise.resolve(false); } // Check expiration: if expired, cannot refresh if (lock.hasExpiration && lock.expiration <= new Date()) { return Promise.resolve(false); } if (!lock.hasExpiration) { return Promise.resolve(false); } clearTimeout(lock.timeoutId); const timeoutId = setTimeout(() => { this.map.delete(key); }, ttl.toMilliseconds()); this.map.set(key, { ...lock, timeoutId, }); return Promise.resolve(true); } async getState(_context, key) { const lockData = this.map.get(key); if (lockData === undefined) { return Promise.resolve(null); } if (!lockData.hasExpiration) { return Promise.resolve({ owner: lockData.owner, expiration: null, }); } if (lockData.expiration <= new Date()) { return Promise.resolve(null); } return Promise.resolve({ owner: lockData.owner, expiration: lockData.expiration, }); } } //# sourceMappingURL=memory-lock-adapter.js.map