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