@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.
1,185 lines • 87 kB
JavaScript
/**
* @module Lock
*/
import {} from "vitest";
import { KeyAlreadyAcquiredLockError, UnownedRefreshLockError, UnownedReleaseLockError, LOCK_EVENTS, } from "../../../lock/contracts/_module-exports.js";
import {} from "../../../utilities/_module-exports.js";
import { TimeSpan } from "../../../utilities/_module-exports.js";
import { LazyPromise } from "../../../async/_module-exports.js";
import { NoOpSerdeAdapter } from "../../../serde/implementations/adapters/_module-exports.js";
import { Serde } from "../../../serde/implementations/derivables/_module-exports.js";
/**
* The `lockProviderTestSuite` function simplifies the process of testing your custom implementation of {@link ILock | `ILock`} with `vitest`.
*
* IMPORT_PATH: `"@daiso-tech/core/lock/test-utilities"`
* @group Utilities
* @example
* ```ts
* import { describe, expect, test, beforeEach } from "vitest";
* import { MemoryLockAdapter } from "@daiso-tech/core/lock/adapters";
* import { LockProvider } from "@daiso-tech/core/lock";
* import { EventBus } from "@daiso-tech/core/event-bus";
* import { MemoryEventBusAdapter } from "@daiso-tech/core/event-bus/adapters";
* import { lockProviderTestSuite } from "@daiso-tech/core/lock/test-utilities";
* import { Serde } from "@daiso-tech/core/serde";
* import { SuperJsonSerdeAdapter } from "@daiso-tech/core/serde/adapters";
* import type { ILockData } from "@daiso-tech/core/lock/contracts";
* import { KeyPrefixer } from "@daiso-tech/core/utilities";
*
* describe("class: LockProvider", () => {
* const eventBus = new EventBus({
* keyPrefixer: new KeyPrefixer("event-bus"),
* adapter: new MemoryEventBusAdapter(),
* });
* const serde = new Serde(new SuperJsonSerdeAdapter());
* let map: Map<string, ILockData>;
* lockProviderTestSuite({
* createLockProvider: () => {
* const lockProvider = new LockProvider({
* serde,
* adapter: new MemoryLockAdapter(),
* eventBus,
* keyPrefixer: new KeyPrefixer("lock"),
* });
* return lockProvider;
* },
* beforeEach,
* describe,
* expect,
* test,
* serde,
* });
* });
* ```
*/
export function lockProviderTestSuite(settings) {
const { expect, test, createLockProvider, describe, beforeEach, serde = new Serde(new NoOpSerdeAdapter()), } = settings;
let lockProvider;
beforeEach(async () => {
lockProvider = await createLockProvider();
});
const TTL = TimeSpan.fromMilliseconds(50);
const DELAY_TIME = TimeSpan.fromMilliseconds(50);
describe("Api tests:", () => {
describe("method: run", () => {
test("Should return string when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const [result, error] = await lock.run(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
});
expect(result).toBe("a");
expect(error).toBeNull();
});
test("Should return null when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
const [result, error] = await lock.run(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
});
expect(result).toBeNull();
expect(error).toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
test("Should work with LazyPromise", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const [result, error] = await lock.run(new LazyPromise(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}));
expect(result).toBe("a");
expect(error).toBeNull();
});
});
describe("method: runOrFail", () => {
test("Should return string when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.runOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
});
expect(result).toBe("a");
});
test("Should throw KeyAlreadyAcquiredLockError when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
const result = lock.runOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
});
await expect(result).rejects.toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
test("Should work with LazyPromise", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.runOrFail(new LazyPromise(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}));
expect(result).toBe("a");
});
});
describe("method: runBlocking", () => {
test("Should return string when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const [result, error] = await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe("a");
expect(error).toBeNull();
});
test("Should return null when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
const [result, error] = await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBeNull();
expect(error).toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
test("Should work with LazyPromise", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const [result, error] = await lock.runBlocking(new LazyPromise(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}), {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe("a");
expect(error).toBeNull();
});
test("Should retry acquire the lock", async () => {
const key = "a";
const ttl = TimeSpan.fromMilliseconds(50);
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
let index = 0;
await lockProvider.addListener(LOCK_EVENTS.NOT_AVAILABLE, (_event) => {
index++;
});
await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
}, {
time: TimeSpan.fromMilliseconds(55),
interval: TimeSpan.fromMilliseconds(5),
});
expect(index).toBeGreaterThan(1);
});
});
describe("method: runBlockingOrFail", () => {
test("Should return string when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.runBlockingOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe("a");
});
test("Should throw KeyAlreadyAcquiredLockError when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
const promise = lock.runBlockingOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await expect(promise).rejects.toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
test("Should work with LazyPromise", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.runBlockingOrFail(new LazyPromise(async () => {
await LazyPromise.delay(DELAY_TIME);
return "a";
}), {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe("a");
});
test("Should retry acquire the lock", async () => {
const key = "a";
const ttl = TimeSpan.fromMilliseconds(50);
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
let index = 0;
await lockProvider.addListener(LOCK_EVENTS.NOT_AVAILABLE, (_event) => {
index++;
});
try {
await lock.runBlockingOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
}, {
time: TimeSpan.fromMilliseconds(55),
interval: TimeSpan.fromMilliseconds(5),
});
}
catch {
/* Empty */
}
expect(index).toBeGreaterThan(1);
});
});
describe("method: acquire", () => {
test("Should return true when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.acquire();
expect(result).toBe(true);
});
test("Should return false when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
const result = await lock.acquire();
expect(result).toBe(false);
});
test("Should not be expired when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isExpired();
expect(result).toBe(false);
});
test("Should be loked when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isLocked();
expect(result).toBe(true);
});
});
describe("method: acquireOrFail", () => {
test("Should not throw KeyAlreadyAcquiredLockError when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = lock.acquireOrFail();
await expect(result).resolves.toBeUndefined();
});
test("Should throw KeyAlreadyAcquiredLockError when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquireOrFail();
const result = lock.acquireOrFail();
await expect(result).rejects.toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
});
describe("method: acquireBlocking", () => {
test("Should return true when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const result = await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe(true);
});
test("Should return false when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const result = await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
expect(result).toBe(false);
});
test("Should not be expired when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const result = await lock.isExpired();
expect(result).toBe(false);
});
test("Should be loked when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const result = await lock.isLocked();
expect(result).toBe(true);
});
test("Should retry acquire the lock", async () => {
const key = "a";
const ttl = TimeSpan.fromMilliseconds(50);
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
let index = 0;
await lockProvider.addListener(LOCK_EVENTS.NOT_AVAILABLE, (_event) => {
index++;
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(55),
interval: TimeSpan.fromMilliseconds(5),
});
expect(index).toBeGreaterThan(1);
});
});
describe("method: acquireBlockingOrFail", () => {
test("Should not throw KeyAlreadyAcquiredLockError when lock is available", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
const promise = lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await expect(promise).resolves.toBeUndefined();
});
test("Should throw KeyAlreadyAcquiredLockError when lock is already acquired", async () => {
const key = "a";
const ttl = null;
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const promise = lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await expect(promise).rejects.toBeInstanceOf(KeyAlreadyAcquiredLockError);
});
test("Should not be expired when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const result = await lock.isExpired();
expect(result).toBe(false);
});
test("Should be loked when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const result = await lock.isLocked();
expect(result).toBe(true);
});
test("Should retry acquire the lock", async () => {
const key = "a";
const ttl = TimeSpan.fromMilliseconds(50);
const lock = lockProvider.create(key, {
ttl,
});
await lock.acquire();
let index = 0;
await lockProvider.addListener(LOCK_EVENTS.NOT_AVAILABLE, (_event) => {
index++;
});
try {
await lock.acquireBlockingOrFail({
time: TimeSpan.fromMilliseconds(55),
interval: TimeSpan.fromMilliseconds(5),
});
}
catch {
/* Empty */
}
expect(index).toBeGreaterThan(1);
});
});
describe("method: release", () => {
test("Should return true when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.release();
expect(result).toBe(true);
});
test("Should return false when released by different owner", async () => {
const key = "a";
const ttl = null;
const owner1 = "b";
const lock1 = lockProvider.create(key, {
ttl,
owner: owner1,
});
await lock1.acquire();
const owner2 = "c";
const lock2 = lockProvider.create(key, {
ttl,
owner: owner2,
});
const result = await lock2.release();
expect(result).toBe(false);
});
test("Should be expired when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.release();
const result = await lock.isExpired();
expect(result).toBe(true);
});
test("Should be not loked when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.release();
const result = await lock.isLocked();
expect(result).toBe(false);
});
});
describe("method: releaseOrFail", () => {
test("Should not throw UnownedReleaseLockError when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = lock.releaseOrFail();
await expect(result).resolves.toBeUndefined();
});
test("Should throw UnownedReleaseLockError when released by different owner", async () => {
const key = "a";
const ttl = null;
const owner1 = "b";
const lock1 = lockProvider.create(key, {
ttl,
owner: owner1,
});
await lock1.acquire();
const owner2 = "c";
const lock2 = lockProvider.create(key, {
ttl,
owner: owner2,
});
const result = lock2.releaseOrFail();
await expect(result).rejects.toBeInstanceOf(UnownedReleaseLockError);
});
test("Should be expired when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.releaseOrFail();
const result = await lock.isExpired();
expect(result).toBe(true);
});
test("Should be not loked when released by same owner", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.releaseOrFail();
const result = await lock.isLocked();
expect(result).toBe(false);
});
});
describe("method: forceRelease", () => {
test("Should release lock no regardless of the owner", async () => {
const key = "a";
const ttl = null;
const owner1 = "b";
const lock1 = lockProvider.create(key, {
ttl,
owner: owner1,
});
await lock1.acquire();
const owner2 = "c";
const lock2 = lockProvider.create(key, {
ttl,
owner: owner2,
});
await lock2.forceRelease();
const result = await lock1.acquire();
expect(result).toBe(true);
});
test("Should be expired when released", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.forceRelease();
const result = await lock.isExpired();
expect(result).toBe(true);
});
test("Should be not loked when released", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await lock.forceRelease();
const result = await lock.isLocked();
expect(result).toBe(false);
});
});
describe("method: isExpired", () => {
test("Should return false when lock has no expiration", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isExpired();
expect(result).toBe(false);
});
test("Should return false when lock has not expired", async () => {
const key = "a";
const owner = "b";
const ttl = TTL;
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isExpired();
expect(result).toBe(false);
});
test("Should return true when lock has expired", async () => {
const key = "a";
const owner = "b";
const ttl = TTL;
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await LazyPromise.delay(ttl.addMilliseconds(25));
const result = await lock.isExpired();
expect(result).toBe(true);
});
});
describe("method: isLocked", () => {
test("Should return true when lock has no expiration", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isLocked();
expect(result).toBe(true);
});
test("Should return true when lock has not expired", async () => {
const key = "a";
const owner = "b";
const ttl = TTL;
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.isLocked();
expect(result).toBe(true);
});
test("Should return false when lock has expired", async () => {
const key = "a";
const owner = "b";
const ttl = TTL;
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await LazyPromise.delay(ttl.addMilliseconds(25));
const result = await lock.isLocked();
expect(result).toBe(false);
});
});
describe("method: refresh", () => {
test("Should return true when refreshed by same owner", async () => {
const key = "a";
const ttl = TTL;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await LazyPromise.delay(ttl);
const result = await lock.refresh();
expect(result).toBe(true);
});
test("Should return false when refreshed by different owner", async () => {
const key = "a";
const ttl = TTL;
const owner1 = "b";
const lock1 = lockProvider.create(key, {
ttl,
owner: owner1,
});
await lock1.acquire();
const owner2 = "c";
const lock2 = lockProvider.create(key, {
ttl,
owner: owner2,
});
const result = await lock2.refresh();
expect(result).toBe(false);
});
test("Should refresh expiration by same owner", async () => {
const key = "a";
const ttl = TTL;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await LazyPromise.delay(ttl.subtractMilliseconds(10));
await lock.refresh();
const time = await lock.getRemainingTime();
expect(time?.toMilliseconds()).toBeGreaterThan(0);
});
});
describe("method: refreshOrFail", () => {
test("Should not throw UnownedRefreshLockError when refreshed by same owner", async () => {
const key = "a";
const ttl = TTL;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
await LazyPromise.delay(ttl);
const result = lock.refreshOrFail();
await expect(result).resolves.toBeUndefined();
});
test("Should throw UnownedRefreshLockError when refreshed by different owner", async () => {
const key = "a";
const ttl = TTL;
const owner1 = "b";
const lock1 = lockProvider.create(key, {
ttl,
owner: owner1,
});
await lock1.acquire();
const owner2 = "c";
const lock2 = lockProvider.create(key, {
ttl,
owner: owner2,
});
const result = lock2.refreshOrFail();
await expect(result).rejects.toBeInstanceOf(UnownedRefreshLockError);
});
test("Should refresh expiration by same owner", async () => {
const key = "a";
const ttl = TTL;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquireOrFail();
await LazyPromise.delay(ttl.subtractMilliseconds(10));
await lock.refresh();
const time = await lock.getRemainingTime();
expect(time?.toMilliseconds()).toBeGreaterThan(0);
});
});
describe("method: getRemainingTime", () => {
test("Should return null when lock is not acquired", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
const result = await lock.getRemainingTime();
expect(result).toBeNull();
});
test("Should return null when lock is acquired and has expiration", async () => {
const key = "a";
const ttl = null;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.getRemainingTime();
expect(result).toBeNull();
});
test("Should return remaining time when lock is not acquired", async () => {
const key = "a";
const ttl = TTL;
const owner = "b";
const lock = lockProvider.create(key, {
ttl,
owner,
});
await lock.acquire();
const result = await lock.getRemainingTime();
expect(result?.toMilliseconds()).toBe(ttl.toMilliseconds());
});
});
describe("method: getOwner", () => {
test("Should return the owner", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
const result = await lock.getOwner();
expect(result).toBe(owner);
});
test("Should return the auto generated owner", async () => {
const key = "a";
const lock = lockProvider.create(key);
const result = await lock.getOwner();
expect(result).toBeDefined();
expect(typeof result).toBe("string");
});
});
});
describe("Event tests:", () => {
describe("class: Lock", () => {
describe("method: run", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.ACQUIRED, (event) => {
event_ = event;
});
await lock.run(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
expect(event_?.ttl?.toMilliseconds()).toBe(TTL.toMilliseconds());
await unsubscribe();
});
test("Should dispatch ReleasedLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.RELEASED, (event) => {
event_ = event;
});
await lock.run(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe(key);
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
test("Should dispatch NotAvailableLockEvent when lock is acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
let event_ = null;
await lock.acquire();
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.NOT_AVAILABLE, (event) => {
event_ = event;
});
await lock.run(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
});
describe("method: runBlocking", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.ACQUIRED, (event) => {
event_ = event;
});
await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
expect(event_?.ttl?.toMilliseconds()).toBe(TTL.toMilliseconds());
await unsubscribe();
});
test("Should dispatch ReleasedLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.RELEASED, (event) => {
event_ = event;
});
await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe(key);
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
test("Should dispatch NotAvailableLockEvent when lock is acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
let event_ = null;
await lock.acquire();
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.NOT_AVAILABLE, (event) => {
event_ = event;
});
await lock.runBlocking(async () => {
await LazyPromise.delay(DELAY_TIME);
}, {
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
});
describe("method: runOrFail", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.ACQUIRED, (event) => {
event_ = event;
});
await lock.runOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
expect(event_?.ttl?.toMilliseconds()).toBe(TTL.toMilliseconds());
await unsubscribe();
});
test("Should dispatch ReleasedLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.RELEASED, (event) => {
event_ = event;
});
await lock.runOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe(key);
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
test("Should dispatch NotAvailableLockEvent when lock is acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
let event_ = null;
await lock.acquire();
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.NOT_AVAILABLE, (event) => {
event_ = event;
});
try {
await lock.runOrFail(async () => {
await LazyPromise.delay(DELAY_TIME);
});
await LazyPromise.delay(DELAY_TIME);
}
catch {
/* Empty */
}
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
});
describe("method: acquire", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.ACQUIRED, (event) => {
event_ = event;
});
await lock.acquire();
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
expect(event_?.ttl?.toMilliseconds()).toBe(TTL.toMilliseconds());
await unsubscribe();
});
test("Should dispatch NotAvailableLockEvent when lock is acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
let event_ = null;
await lock.acquire();
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.NOT_AVAILABLE, (event) => {
event_ = event;
});
await lock.acquire();
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
});
describe("method: acquireBlocking", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = null;
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.ACQUIRED, (event) => {
event_ = event;
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
expect(event_?.ttl?.toMilliseconds()).toBe(TTL.toMilliseconds());
await unsubscribe();
});
test("Should dispatch NotAvailableLockEvent when lock is acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
});
let event_ = null;
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
const unsubscribe = await lockProvider.subscribe(LOCK_EVENTS.NOT_AVAILABLE, (event) => {
event_ = event;
});
await lock.acquireBlocking({
time: TimeSpan.fromMilliseconds(5),
interval: TimeSpan.fromMilliseconds(5),
});
await LazyPromise.delay(DELAY_TIME);
expect(event_?.key).toBe("a");
expect(event_?.owner).toBe(owner);
await unsubscribe();
});
});
describe("method: acquireOrFail", () => {
test("Should dispatch AcquiredLockEvent when lock is not acquired", async () => {
const key = "a";
const owner = "b";
const lock = lockProvider.create(key, {
owner,
ttl: TTL,
});
let event_ = n