API reference / @evolu/common / Task / createSemaphore
Function: createSemaphore()
function createSemaphore(maxConcurrent): Semaphore;
Defined in: packages/common/src/Task.ts:625
Creates a semaphore that limits concurrent async Tasks to the specified count.
A semaphore controls access to a resource by maintaining a count of available permits. Tasks acquire a permit before executing and release it when complete.
For mutual exclusion (exactly one Task at a time), consider using createMutex instead.
Example
// Allow maximum 3 concurrent Tasks
const semaphore = createSemaphore(PositiveInt.orThrow(3));
let currentConcurrent = 0;
const events: Array<string> = [];
const fetchData = (id: number) =>
toTask<number, never>(async (context) => {
currentConcurrent++;
events.push(`start ${id} (concurrent: ${currentConcurrent})`);
await wait("10ms")(context);
currentConcurrent--;
events.push(`end ${id} (concurrent: ${currentConcurrent})`);
return ok(id * 10);
});
// These will execute with at most 3 running concurrently
const results = await Promise.all([
semaphore.withPermit(fetchData(1))(),
semaphore.withPermit(fetchData(2))(),
semaphore.withPermit(fetchData(3))(),
semaphore.withPermit(fetchData(4))(), // waits for one above to complete
semaphore.withPermit(fetchData(5))(), // waits for permit
]);
expect(results.map(getOrThrow)).toEqual([10, 20, 30, 40, 50]);
expect(events).toMatchInlineSnapshot(`
[
"start 1 (concurrent: 1)",
"start 2 (concurrent: 2)",
"start 3 (concurrent: 3)",
"end 1 (concurrent: 2)",
"start 4 (concurrent: 3)",
"end 2 (concurrent: 2)",
"start 5 (concurrent: 3)",
"end 3 (concurrent: 2)",
"end 4 (concurrent: 1)",
"end 5 (concurrent: 0)",
]
`);
Parameters
| Parameter | Type |
|---|---|
maxConcurrent | number & Brand<"Int"> & Brand<"NonNegative"> & Brand<"Positive"> |