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.

186 lines 8.81 kB
/** * @module Lock */ import { v4 } from "uuid"; import {} from "../../../../event-bus/contracts/_module.js"; import { NoOpEventBusAdapter } from "../../../../event-bus/implementations/adapters/_module.js"; import { EventBus } from "../../../../event-bus/implementations/derivables/_module.js"; import {} from "../../../../lock/contracts/_module.js"; import { LockSerdeTransformer } from "../../../../lock/implementations/derivables/lock-provider/lock-serde-transformer.js"; import { Lock } from "../../../../lock/implementations/derivables/lock-provider/lock.js"; import { resolveLockAdapter } from "../../../../lock/implementations/derivables/lock-provider/resolve-lock-adapter.js"; import { Namespace } from "../../../../namespace/_module.js"; import {} from "../../../../serde/contracts/_module.js"; import { NoOpSerdeAdapter } from "../../../../serde/implementations/adapters/_module.js"; import { Serde } from "../../../../serde/implementations/derivables/_module.js"; import {} from "../../../../task/contracts/_module.js"; import {} from "../../../../time-span/contracts/_module.js"; import { TimeSpan } from "../../../../time-span/implementations/_module.js"; import { CORE, resolveOneOrMore, callInvokable, } from "../../../../utilities/_module.js"; /** * * IMPORT_PATH: `"@daiso-tech/core/lock"` * @group Derivables */ export const DEFAULT_LOCK_PROVIDER_NAMESPACE = new Namespace("@lock"); /** * `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 { eventBus; originalAdapter; adapter; namespace; creatLockId; defaultTtl; defaultBlockingInterval; defaultBlockingTime; defaultRefreshTime; serde; serdeTransformerName; /** * @example * ```ts * import { KyselyLockAdapter } from "@daiso-tech/core/lock/kysely-lock-adapter"; * import { LockProvider } from "@daiso-tech/core/lock"; * import { Serde } from "@daiso-tech/core/serde"; * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/super-json-serde-adapter"; * import Sqlite from "better-sqlite3"; * import { Kysely, SqliteDialect } from "kysely"; * * const lockAdapter = new KyselyLockAdapter({ * kysely: new Kysely({ * dialect: new SqliteDialect({ * database: new Sqlite("local.db"), * }), * }); * }); * // 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), createLockId = () => v4(), serde = new Serde(new NoOpSerdeAdapter()), namespace = DEFAULT_LOCK_PROVIDER_NAMESPACE, adapter, eventBus = new EventBus({ adapter: new NoOpEventBusAdapter(), }), serdeTransformerName = "", } = settings; this.serde = serde; this.defaultBlockingInterval = TimeSpan.fromTimeSpan(defaultBlockingInterval); this.defaultBlockingTime = TimeSpan.fromTimeSpan(defaultBlockingTime); this.defaultRefreshTime = TimeSpan.fromTimeSpan(defaultRefreshTime); this.creatLockId = createLockId; this.namespace = namespace; this.defaultTtl = defaultTtl === null ? null : TimeSpan.fromTimeSpan(defaultTtl); this.eventBus = eventBus; this.serdeTransformerName = serdeTransformerName; this.originalAdapter = adapter; this.adapter = resolveLockAdapter(adapter); this.registerToSerde(); } registerToSerde() { const transformer = new LockSerdeTransformer({ originalAdapter: this.originalAdapter, adapter: this.adapter, defaultBlockingInterval: this.defaultBlockingInterval, defaultBlockingTime: this.defaultBlockingTime, defaultRefreshTime: this.defaultRefreshTime, eventBus: this.eventBus, namespace: this.namespace, 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 `}. */ asTask(eventName) { return this.eventBus.asTask(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); } /** * @example * ```ts * import { LockProvider } from "@daiso-tech/core/lock"; * import { MemoryLockAdapter } from "@daiso-tech/core/lock/memory-lock-adapter"; * import { Namespace } from "@daiso-tech/core/namespace"; * import { Serde } from "@daiso-tech/core/serde"; * import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/super-json-serde-adapter"; * * 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, lockId = callInvokable(this.creatLockId), } = settings; const keyObj = this.namespace.create(key); return new Lock({ namespace: this.namespace, adapter: this.adapter, originalAdapter: this.originalAdapter, eventDispatcher: this.eventBus, key: keyObj, lockId, ttl: ttl === null ? null : TimeSpan.fromTimeSpan(ttl), serdeTransformerName: this.serdeTransformerName, defaultBlockingInterval: this.defaultBlockingInterval, defaultBlockingTime: this.defaultBlockingTime, defaultRefreshTime: this.defaultRefreshTime, }); } } //# sourceMappingURL=lock-provider.js.map