BEAM waiter registry for blocking list commands (BLPOP, BRPOP, BLMOVE, BLMPOP).
Uses an ETS table (:ferricstore_waiters) with entries
{key, client_pid, deadline_ms, registered_at}. When a list is empty, the
client BEAM process registers itself and enters a receive block with an
after clause matching the timeout. When another client pushes to that key,
the push path calls notify_push/1 which wakes the oldest waiter (FIFO by
registration timestamp).
The BEAM runtime handles the timeout with zero polling -- no busy wait, no periodic check loop. Multiple waiters on the same key are served FIFO by registration timestamp.
ETS table
The table is a :duplicate_bag keyed by the watched key. Each entry is:
{key, pid, deadline_ms, registered_at_mono}key-- the Redis key being watchedpid-- the client connection processdeadline_ms-- absolute monotonic deadline (0 = infinite)registered_at_mono--System.monotonic_time(:microsecond)for FIFO ordering
Summary
Functions
Removes all waiters registered by pid.
Returns the number of waiters registered for key.
Initializes the waiter ETS table. Must be called once at application start.
Notifies the oldest waiter for key that a value has been pushed.
Registers the calling process as a waiter for key.
Returns the total number of waiters across all keys.
Unregisters a specific waiter for key.
Functions
@spec cleanup(pid()) :: :ok
Removes all waiters registered by pid.
Called when a client disconnects to prevent stale entries.
Parameters
pid-- the disconnected client's pid
@spec count(binary()) :: non_neg_integer()
Returns the number of waiters registered for key.
Useful for testing and monitoring.
@spec init() :: :ok
Initializes the waiter ETS table. Must be called once at application start.
Notifies the oldest waiter for key that a value has been pushed.
Called from the push path (LPUSH/RPUSH) when data is added to a key.
Wakes the oldest registered waiter (FIFO) by sending {:waiter_notify, key}
to its pid. Returns the notified pid, or nil if no waiters exist.
Parameters
key-- the Redis key that received a push
@spec register(binary(), pid(), non_neg_integer()) :: :ok
Registers the calling process as a waiter for key.
Parameters
key-- the Redis key to wait onpid-- the client connection process piddeadline_ms-- absolute monotonic deadline in ms (0 = block forever)
Returns
:ok
@spec total_count() :: non_neg_integer()
Returns the total number of waiters across all keys.
Useful for testing and monitoring.
Unregisters a specific waiter for key.
Parameters
key-- the Redis keypid-- the client connection process pid