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.

184 lines 8.67 kB
/** * @module Lock */ import { TimeSpan, CORE, resolveFactory, resolveOneOrMore, } from "../../../../utilities/_module-exports.js"; import { KeyPrefixer } from "../../../../utilities/_module-exports.js"; import {} from "../../../../lock/contracts/_module-exports.js"; import { LazyPromise } from "../../../../async/_module-exports.js"; import { EventBus } from "../../../../event-bus/implementations/derivables/_module-exports.js"; import { MemoryEventBusAdapter } from "../../../../event-bus/implementations/adapters/_module-exports.js"; import { v4 } from "uuid"; import { Lock } from "../../../../lock/implementations/derivables/lock-provider/lock.js"; import { LockState, } from "../../../../lock/implementations/derivables/lock-provider/lock-state.js"; import { isDatabaseLockAdapter } from "../../../../lock/implementations/derivables/lock-provider/is-database-lock-adapter.js"; import { DatabaseLockAdapter } from "../../../../lock/implementations/derivables/lock-provider/database-lock-adapter.js"; import { LockSerdeTransformer } from "../../../../lock/implementations/derivables/lock-provider/lock-serde-transformer.js"; /** * `LockProvider` class can be derived from any {@link ILockAdapter | `ILockAdapter`} or {@link IDatabaseLockAdapter | `IDatabaseLockAdapter`}. * * Note the {@link ILock | `ILock`} instances created by the `LockProvider` class are serializable and deserializable, * allowing them to be seamlessly transferred across different servers, processes, and databases. * This can be done directly using {@link IFlexibleSerde | `IFlexibleSerde`} or indirectly through components that rely on {@link IFlexibleSerde | `IFlexibleSerde`} internally. * * IMPORT_PATH: `"@daiso-tech/core/lock"` * @group Derivables */ export class LockProvider { lockStore = {}; eventBus; adapter; keyPrefixer; createOwnerId; defaultTtl; defaultBlockingInterval; defaultBlockingTime; defaultRefreshTime; serde; lazyPromiseFactory; serdeTransformerName; /** * @example * ```ts * import { SqliteLockAdapter } from "@daiso-tech/core/lock/adapters"; * import { LockProvider } from "@daiso-tech/core/lock"; * import { KeyPrefixer } from "@daiso-tech/core/utilities"; * import { Serde } from "@daiso-tech/core/serde"; * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/adapters"; * import Sqlite from "better-sqlite3"; * * const database = new Sqlite("local.db"); * const lockAdapter = new SqliteLockAdapter({ * database, * }); * // You need initialize the adapter once before using it. * await lockAdapter.init(); * * const serde = new Serde(new SuperJsonSerdeAdapter()) * const lockProvider = new LockProvider({ * keyPrefixer: new KeyPrefixer("lock"), * serde, * adapter: lockAdapter, * }); * ``` */ constructor(settings) { const { defaultTtl = TimeSpan.fromMinutes(5), defaultBlockingInterval = TimeSpan.fromSeconds(1), defaultBlockingTime = TimeSpan.fromMinutes(1), defaultRefreshTime = TimeSpan.fromMinutes(5), createOwnerId = () => v4(), serde, keyPrefixer, adapter, eventBus = new EventBus({ keyPrefixer: new KeyPrefixer("events"), adapter: new MemoryEventBusAdapter(), }), serdeTransformerName = "", lazyPromiseFactory = (invokable) => new LazyPromise(invokable), } = settings; this.serde = serde; this.defaultBlockingInterval = defaultBlockingInterval; this.defaultBlockingTime = defaultBlockingTime; this.defaultRefreshTime = defaultRefreshTime; this.createOwnerId = createOwnerId; this.keyPrefixer = keyPrefixer; this.defaultTtl = defaultTtl; this.eventBus = eventBus; this.lazyPromiseFactory = resolveFactory(lazyPromiseFactory); this.serdeTransformerName = serdeTransformerName; if (isDatabaseLockAdapter(adapter)) { this.adapter = new DatabaseLockAdapter(adapter); } else { this.adapter = adapter; } this.registerToSerde(); } registerToSerde() { const transformer = new LockSerdeTransformer({ adapter: this.adapter, createLazyPromise: (asyncFn) => this.createLazyPromise(asyncFn), defaultBlockingInterval: this.defaultBlockingInterval, defaultBlockingTime: this.defaultBlockingTime, defaultRefreshTime: this.defaultRefreshTime, eventBus: this.eventBus, keyPrefixer: this.keyPrefixer, lockStore: this.lockStore, serdeTransformerName: this.serdeTransformerName, }); for (const serde of resolveOneOrMore(this.serde)) { serde.registerCustom(transformer, CORE); } } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ addListener(eventName, listener) { return this.eventBus.addListener(eventName, listener); } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ removeListener(eventName, listener) { return this.eventBus.removeListener(eventName, listener); } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ listenOnce(eventName, listener) { return this.eventBus.listenOnce(eventName, listener); } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ asPromise(eventName) { return this.eventBus.asPromise(eventName); } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ subscribeOnce(eventName, listener) { return this.eventBus.subscribeOnce(eventName, listener); } /** * You can listen to the following {@link LockEvents | `LockEvents`} of all {@link ILock | `ILock`} instances created by the {@link ILockProvider | `ILockProvider`}. * To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}. */ subscribe(eventName, listener) { return this.eventBus.subscribe(eventName, listener); } createLazyPromise(asyncFn) { return new LazyPromise(asyncFn); } /** * @example * ```ts * import { LockProvider } from "@daiso-tech/core/lock"; * import { MemoryLockAdapter } from "@daiso-tech/core/lock/adapters"; * import { KeyPrefixer } from "@daiso-tech/core/utilities"; * import { Serde } from "@daiso-tech/core/serde"; * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/adapters"; * * const lockProvider = new LockProvider({ * adapter: new MemoryLockAdapter(), * keyPrefixer: new KeyPrefixer("lock"), * serde: new Serde(new SuperJsonSerdeAdapter()) * }); * * const lock = lockProvider.create("a"); * ``` */ create(key, settings = {}) { const { ttl = this.defaultTtl, owner = this.createOwnerId() } = settings; const keyObj = this.keyPrefixer.create(key); return new Lock({ adapter: this.adapter, createLazyPromise: (asyncFn) => this.createLazyPromise(asyncFn), lockState: new LockState(this.lockStore, keyObj.prefixed), eventDispatcher: this.eventBus, key: keyObj, owner, ttl, expirationInMs: null, defaultBlockingInterval: this.defaultBlockingInterval, defaultBlockingTime: this.defaultBlockingTime, defaultRefreshTime: this.defaultRefreshTime, }); } } //# sourceMappingURL=lock-provider.js.map