Skip to content

PartitionedSemaphore.ts

The PartitionedSemaphore module provides a semaphore for limiting concurrency across a shared permit pool while keeping waiters grouped by partition key. A PartitionedSemaphore<K> is useful when many independent groups of work compete for the same bounded resource and each group should make progress without one busy group monopolizing released permits.

Since v4.0.0



Gets the current number of available permits.

When to use

Use to inspect a snapshot of how many permits are currently free.

Details

Running the returned effect reads the semaphore’s current availability. Taking permits decreases availability, and releasing permits can increase it up to the semaphore capacity.

Gotchas

Reading availability does not reserve permits.

See

  • capacity for the fixed total permit capacity
  • release for returning permits to the shared pool
  • withPermitsIfAvailable for running only when permits are immediately available

Signature

declare const available: <K>(self: PartitionedSemaphore<K>) => Effect.Effect<number>

Source

Since v4.0.0

Returns an effect that releases permits back to the shared pool and returns the current available permit count.

When to use

Use when you need to return permits acquired with take in a lower-level partitioned permit protocol with explicit release control.

Details

Released permits are first assigned to waiting partitions in round-robin order. Only permits not needed by waiters increase the available count, which is capped at the semaphore capacity.

See

  • take for manual acquisition
  • withPermits for automatic acquire and release around an effect
  • available for reading the permit count without releasing

Signature

declare const release: {
(permits: number): <K>(self: PartitionedSemaphore<K>) => Effect.Effect<number>
<K>(self: PartitionedSemaphore<K>, permits: number): Effect.Effect<number>
}

Source

Since v4.0.0

Returns an effect that acquires the requested number of permits for the given partition key.

When to use

Use when you need manual permit acquisition for a partition and want to control acquisition and release as separate effects.

Details

If enough permits are available, the effect completes immediately. Otherwise it waits until released permits are assigned to this partition.

Gotchas

Requests for more permits than the semaphore capacity never complete. Requests for zero or a negative number of permits complete without acquiring anything.

See

  • release for manually returning permits to the shared pool
  • withPermits for automatic acquire and release around an effect
  • withPermit for acquiring exactly one permit around an effect

Signature

declare const take: {
<K>(key: K, permits: number): (self: PartitionedSemaphore<K>) => Effect.Effect<void>
<K>(self: PartitionedSemaphore<K>, key: K, permits: number): Effect.Effect<void>
}

Source

Since v4.0.0

Runs an effect after acquiring one permit for a partition, then releases the permit when the effect exits.

When to use

Use to guard partitioned work with exactly one permit and automatic release when the effect exits.

Details

This is the single-permit variant of withPermits. The permit is released even if the wrapped effect fails or is interrupted.

See

  • withPermits for acquiring a weighted number of permits
  • withPermitsIfAvailable for running only when permits are immediately available
  • take for manual acquisition
  • release for manual release

Signature

declare const withPermit: {
<K>(self: PartitionedSemaphore<K>, key: K): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<K, A, E, R>(self: PartitionedSemaphore<K>, key: K, effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>
}

Source

Since v4.0.0

Runs an effect after acquiring permits for a partition, then releases those permits when the effect exits.

When to use

Use to guard weighted partitioned work with automatic permit acquisition and release around an effect.

Details

Permit acquisition may wait according to take semantics. Once acquired, the permits are released even if the wrapped effect fails or is interrupted.

Gotchas

Requests for more permits than the semaphore capacity never complete. Requests for zero or a negative number of permits run the effect without acquiring anything.

See

  • withPermit for the single-permit variant
  • withPermitsIfAvailable for running only when permits are immediately available
  • take for manual acquisition
  • release for manual release

Signature

declare const withPermits: {
<K>(
self: PartitionedSemaphore<K>,
key: K,
permits: number
): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
<K, A, E, R>(
self: PartitionedSemaphore<K>,
key: K,
permits: number,
effect: Effect.Effect<A, E, R>
): Effect.Effect<A, E, R>
}

Source

Since v4.0.0

Runs an effect only when the requested permits can be acquired immediately, returning the result in Some.

When to use

Use when guarded work should run only if the shared permit pool can provide the requested permits immediately.

Details

If the permits are not available, the effect is not run and the result is None. When permits are acquired, they are released after the wrapped effect completes, fails, or is interrupted. Requests for zero or a negative number of permits run the effect and return Some.

See

  • withPermits for the keyed variant that waits until permits are available for a partition

Signature

declare const withPermitsIfAvailable: {
<K>(
self: PartitionedSemaphore<K>,
permits: number
): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>
<K, A, E, R>(
self: PartitionedSemaphore<K>,
permits: number,
effect: Effect.Effect<A, E, R>
): Effect.Effect<Option.Option<A>, E, R>
}

Source

Since v4.0.0

Creates a PartitionedSemaphore inside an Effect.

When to use

Use when semaphore construction should stay inside an Effect workflow.

Details

The permits option sets the shared permit capacity. The resulting semaphore tracks waiters by partition key and distributes released permits across waiting partitions in round-robin order.

Gotchas

Negative permit counts are clamped to 0. Non-finite permit counts create an unbounded semaphore.

See

  • makeUnsafe for synchronous construction

Signature

declare const make: <K = unknown>(options: { readonly permits: number }) => Effect.Effect<PartitionedSemaphore<K>>

Source

Since v3.19.4

Constructs a PartitionedSemaphore synchronously, outside of Effect.

When to use

Use when you need to construct a partitioned semaphore synchronously outside an Effect workflow.

Details

Negative permit counts are clamped to 0. Non-finite permit counts create an unbounded semaphore whose acquire and release operations complete immediately.

See

  • make for creating a partitioned semaphore inside Effect

Signature

declare const makeUnsafe: <K = unknown>(options: { readonly permits: number }) => PartitionedSemaphore<K>

Source

Since v3.19.4

Gets the total capacity.

When to use

Use to inspect the fixed number of permits configured for the semaphore.

Details

Capacity is stored when the semaphore is created and does not change as permits are acquired or released.

See

  • available for the current number of free permits

Signature

declare const capacity: <K>(self: PartitionedSemaphore<K>) => number

Source

Since v4.0.0

Alias interface for a PartitionedSemaphore keyed by values of type K.

When to use

Use as an alternate exported name for a partitioned permit pool keyed by K.

Details

This interface does not add members beyond PartitionedSemaphore; it provides an alternate exported name for APIs that refer to a partitioned permit pool.

Signature

export interface Partitioned<in K> extends PartitionedSemaphore<K> {}

Source

Since v4.0.0

A PartitionedSemaphore controls access to a shared permit pool while tracking waiters by partition key.

When to use

Use to coordinate shared permits across partition keys so waiting groups make progress without one group monopolizing the pool.

Details

Waiting permits are distributed across partitions in round-robin order.

Signature

export interface PartitionedSemaphore<in K> {
readonly [PartitionedTypeId]: PartitionedTypeId
readonly capacity: number
readonly available: Effect.Effect<number>
readonly take: (key: K, permits: number) => Effect.Effect<void>
readonly release: (permits: number) => Effect.Effect<number>
readonly withPermits: (key: K, permits: number) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
readonly withPermit: (key: K) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
readonly withPermitsIfAvailable: (
permits: number
) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>
}

Source

Since v3.19.4

Runtime type identifier used to mark values that implement PartitionedSemaphore.

Details

This marker is part of the runtime representation of partitioned semaphore values.

Signature

declare const PartitionedTypeId: "~effect/PartitionedSemaphore"

Source

Since v4.0.0

Literal type of the PartitionedSemaphore runtime type identifier.

When to use

Use to type fields that store the exact PartitionedSemaphore runtime marker.

Details

Use this type when declaring fields that must contain the exact PartitionedTypeId marker value.

Signature

type PartitionedTypeId = "~effect/PartitionedSemaphore"

Source

Since v4.0.0