Effect.ts: Absence as First-Class

State ManagementLesson 34 of 51

34. Semaphore - Limited Access Permits

Control HOW MANY concurrent operations can access resources

Code Example
const program = Effect.gen(function* () {
  // Only 3 concurrent database connections
  const semaphore = yield* Semaphore.make(3);

  const processUser = (id: string) =>
    semaphore.withPermits(1)(
      Effect.gen(function* () {
        yield* Console.log(`Processing ${id}`);
        yield* Effect.sleep("1 second");
        return `Done: ${id}`;
      })
    );

  // Process 10 users - but only 3 at a time!
  yield* Effect.all(
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(i =>
      processUser(`user${i}`)
    ),
    { concurrency: "unbounded" }  // Still limited by semaphore!
  );
});
Interactive Example
return `Semaphore concept!

Semaphore.make(2)
→ Only 2 permits available

4 tasks request permits:
- Task 1 & 2: Get permits (run)
- Task 3 & 4: Wait for permits

When Task 1 finishes:
- Releases permit
- Task 3 gets it (runs)

Max concurrent: 2 (limited by semaphore)

Resource limiting!

Note: Semaphore requires Effect runtime
setup not available in browser demo.`;
Explanation

Semaphore: resource availability is limited (permits are absent).

Traditional approach: hope you don't overload resources. Semaphore types limited resource availability:

  • 3 permits available = only 3 resources exist
  • 4th request: access is absent (must wait)
  • No assumptions about resource availability
  • withPermits: acquire absent permit, auto-release

Absence-first resource control: permits are absent until available!


Part 34 of 51 in the Effect.ts Absence Modeling series