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.

181 lines 8.63 kB
/** * @module Lock */ import { TimeSpan, CORE, resolveOneOrMore, resolveInvokable, callInvokable, } from "../../../../utilities/_module-exports.js"; import { Namespace } 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 ISerderRegister | `ISerderRegister`} or indirectly through components that rely on {@link ISerderRegister | `ISerderRegister`} internally. * * IMPORT_PATH: `"@daiso-tech/core/lock"` * @group Derivables */ export class LockProvider { lockStore = {}; eventBus; adapter; namespace; 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 { 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({ * 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, namespace = new Namespace(["@", "lock"]), adapter, eventBus = new EventBus({ 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.namespace = namespace; this.defaultTtl = defaultTtl; this.eventBus = eventBus; this.lazyPromiseFactory = resolveInvokable(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, namespace: this.namespace, lockStore: this.lockStore, serdeTransformerName: this.serdeTransformerName, }); for (const serde of resolveOneOrMore(this.serde)) { serde.registerCustom(transformer, CORE); } } /** * You can listen to the following {@link LockEventMap | `LockEventMap`} 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 LockEventMap | `LockEventMap`} 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 LockEventMap | `LockEventMap`} 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 LockEventMap | `LockEventMap`} 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 LockEventMap | `LockEventMap`} 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 LockEventMap | `LockEventMap`} 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 this.lazyPromiseFactory(asyncFn); } /** * @example * ```ts * import { LockProvider } from "@daiso-tech/core/lock"; * import { MemoryLockAdapter } from "@daiso-tech/core/lock/adapters"; * import { Namespace } 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(), * namespace: new Namespace("lock"), * serde: new Serde(new SuperJsonSerdeAdapter()) * }); * * const lock = lockProvider.create("a"); * ``` */ create(key, settings = {}) { const { ttl = this.defaultTtl, owner = callInvokable(this.createOwnerId), } = settings; const keyObj = this.namespace._getInternal().create(key); return new Lock({ adapter: this.adapter, createLazyPromise: (asyncFn) => this.createLazyPromise(asyncFn), lockState: new LockState(this.lockStore, keyObj.namespaced), eventDispatcher: this.eventBus, key: keyObj, owner, ttl, serdeTransformerName: this.serdeTransformerName, defaultBlockingInterval: this.defaultBlockingInterval, defaultBlockingTime: this.defaultBlockingTime, defaultRefreshTime: this.defaultRefreshTime, }); } } //# sourceMappingURL=lock-provider.js.map