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

ParameterType
maxConcurrentnumber & Brand<"Int"> & Brand<"NonNegative"> & Brand<"Positive">

Returns

Semaphore

Was this page helpful?