GlobalSemaphore (GlobalSemaphore v0.4.0)

Copy Markdown View Source

Cluster-wide semaphore using Erlang's :global module.

Creates a singleton GenServer per name that limits concurrency across all nodes in the cluster. Each semaphore name operates independently, allowing different limits for different resources.

Configuration

config :global_semaphore, :limits,
  pdf_api: 3,
  email_api: 5,
  payment_api: 2

Usage

GlobalSemaphore.with_permit(:pdf_api, fn ->
  # Only 3 concurrent executions allowed cluster-wide
end)

# Priority (lower number = higher priority, default 5)
GlobalSemaphore.with_permit({:pdf_api, 1}, fn -> ... end)   # high
GlobalSemaphore.with_permit({:pdf_api, 5}, fn -> ... end)   # normal (default)
GlobalSemaphore.with_permit({:pdf_api, 10}, fn -> ... end)  # low

Introspection

GlobalSemaphore.list_names()
#=> [:pdf_api]

GlobalSemaphore.status(:pdf_api)
#=> %{
#     name: :pdf_api,
#     max: 3,
#     holders: [%{pid: pid, node: :node1, acquired_at: ~U[...]}],
#     waiters: [%{pid: pid, node: :node2, priority: 5, enqueued_at: ~U[...]}]
#   }

Summary

Functions

Returns a specification to start this module under a supervisor.

Returns the names of all semaphores currently running in the cluster.

Returns the current status of the semaphore with the given name.

Returns the status of all semaphores currently running in the cluster.

Executes the given function with concurrency limit.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

list_names()

@spec list_names() :: [term()]

Returns the names of all semaphores currently running in the cluster.

start_link(name)

status(name)

@spec status(term()) ::
  %{name: term(), max: non_neg_integer(), holders: [map()], waiters: [map()]}
  | nil

Returns the current status of the semaphore with the given name.

Returns nil if no semaphore with that name is running.

Holders are sorted by acquired_at and waiters are in grant order.

status_all()

@spec status_all() :: [map()]

Returns the status of all semaphores currently running in the cluster.

with_permit(name_or_tuple, fun)

@spec with_permit(term() | {term(), integer()}, (-> result)) :: result
when result: term()

Executes the given function with concurrency limit.

Acquires a permit, executes the function, then releases. Handles exceptions safely.