@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.97 kB
JavaScript
/**
* @module SharedLock
*/
import { CORE, resolveOneOrMore, callInvokable, } from "../../../../utilities/_module-exports.js";
import {} from "../../../../utilities/_module-exports.js";
import { EventBus } from "../../../../event-bus/implementations/derivables/_module-exports.js";
import { MemoryEventBusAdapter } from "../../../../event-bus/implementations/adapters/_module.js";
import { v4 } from "uuid";
import { resolveDatabaseSharedLockAdapter } from "../../../../shared-lock/implementations/derivables/shared-lock-provider/resolve-database-shared-lock-adapter.js";
import { SharedLockSerdeTransformer } from "../../../../shared-lock/implementations/derivables/shared-lock-provider/shared-lock-serde-transformer.js";
import { SharedLock } from "../../../../shared-lock/implementations/derivables/shared-lock-provider/shared-lock.js";
import { Namespace } from "../../../../namespace/namespace.js";
import { TimeSpan } from "../../../../time-span/implementations/_module-exports.js";
/**
*
* IMPORT_PATH: `"@daiso-tech/core/shared-lock"`
* @group Derivables
*/
export const DEFAULT_SHARED_LOCK_NAMESPACE = new Namespace("@shared-lock");
/**
* `SharedLockProvider` class can be derived from any {@link ISharedLockAdapter | `ISharedLockAdapter`} or {@link IDatabaseSharedLockAdapter | `IDatabaseSharedLockAdapter`}.
*
* Note the {@link ISharedLock | `ISharedLock`} instances created by the `SharedLockProvider` 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/shared-lock"`
* @group Derivables
*/
export class SharedLockProvider {
eventBus;
originalAdapter;
adapter;
namespace;
creatLockId;
defaultTtl;
defaultBlockingInterval;
defaultBlockingTime;
defaultRefreshTime;
serde;
serdeTransformerName;
/**
* @example
* ```ts
* import { KyselySharedLockAdapter } from "@daiso-tech/core/shared-lock/kysely-shared-lock-adapter";
* import { SharedLockProvider } from "@daiso-tech/core/shared-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 sharedLockAdapter = new KyselySharedLockAdapter({
* kysely: new Kysely({
* dialect: new SqliteDialect({
* database: new Sqlite("local.db"),
* }),
* });
* });
* // You need initialize the adapter once before using it.
* await sharedLockAdapter.init();
*
* const serde = new Serde(new SuperJsonSerdeAdapter())
* const lockProvider = new SharedLockProvider({
* serde,
* adapter: sharedLockAdapter,
* });
* ```
*/
constructor(settings) {
const { defaultTtl = TimeSpan.fromMinutes(5), defaultBlockingInterval = TimeSpan.fromSeconds(1), defaultBlockingTime = TimeSpan.fromMinutes(1), defaultRefreshTime = TimeSpan.fromMinutes(5), createLockId = () => v4(), serde, namespace = DEFAULT_SHARED_LOCK_NAMESPACE, adapter, eventBus = new EventBus({
adapter: new MemoryEventBusAdapter(),
}), 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 = resolveDatabaseSharedLockAdapter(adapter);
this.registerToSerde();
}
registerToSerde() {
const transformer = new SharedLockSerdeTransformer({
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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* 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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* 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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* 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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* 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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* 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 SharedLockEventMap | `SharedLockEventMap`} of all {@link ISharedLock | `ISharedLock`} instances created by the {@link ISharedLockProvider | `ISharedLockProvider`}.
* To understand how this method works, refer to {@link IEventListenable | `IEventListenable `}.
*/
subscribe(eventName, listener) {
return this.eventBus.subscribe(eventName, listener);
}
/**
* @example
* ```ts
* import { SharedLockProvider } from "@daiso-tech/core/shared-lock";
* import { MemorySharedLockAdapter } from "@daiso-tech/core/shared-lock/memory-shared-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 SharedLockProvider({
* adapter: new MemorySharedLockAdapter(),
* namespace: new Namespace("shared_lock"),
* serde: new Serde(new SuperJsonSerdeAdapter())
* });
*
* const sharedLock = lockProvider.create("a");
* ```
*/
create(key, settings) {
const { ttl = this.defaultTtl, lockId = callInvokable(this.creatLockId), limit, } = settings;
const keyObj = this.namespace.create(key);
return new SharedLock({
limit,
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=shared-lock-provider.js.map