@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
JavaScript
/**
* @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