@frozor/lock
v1.0.0
Published
Concurrency control primitives for async JavaScript: Lock, MultiLock, and Semaphore
Maintainers
Readme
@frozor/lock
Concurrency control primitives for async JavaScript/TypeScript: Lock, MultiLock, and Semaphore.
Installation
npm install @frozor/lockAPI
Lock
A mutual exclusion lock. Only one acquire call runs at a time; others queue up in FIFO order.
import { Lock } from '@frozor/lock';
const lock = new Lock();
// Only one of these will run at a time
await Promise.all([
lock.acquire(async () => {
await writeToFile('hello');
}),
lock.acquire(async () => {
await writeToFile('world');
}),
]);
// Check how many callers are waiting
console.log(lock.queueLength);MultiLock
Manages independent locks keyed by string ID. Locks are created on demand and cleaned up automatically when their queue drains.
import { MultiLock } from '@frozor/lock';
const locks = new MultiLock();
// These two calls run concurrently (different IDs)
await Promise.all([
locks.acquire('user-1', () => updateUser('user-1')),
locks.acquire('user-2', () => updateUser('user-2')),
]);
// These two calls run sequentially (same ID)
await Promise.all([
locks.acquire('user-1', () => updateUser('user-1')),
locks.acquire('user-1', () => updateUser('user-1')),
]);Semaphore
Limits concurrency to a maximum number of simultaneous operations.
import { Semaphore } from '@frozor/lock';
// Allow up to 3 concurrent requests
const semaphore = new Semaphore(3);
const urls = [/* ... */];
await Promise.all(
urls.map(url =>
semaphore.acquire(() => fetch(url))
)
);Passing undefined (or no argument) disables the concurrency limit — acquire runs work immediately:
const semaphore = new Semaphore(); // no limit
await semaphore.acquire(() => doWork()); // runs immediatelyMaybePromise<T>
Utility type used by all acquire methods. Your work callback can return either T or Promise<T>.
import type { MaybePromise } from '@frozor/lock';License
MIT
