Ferricstore.Waiters (ferricstore v0.3.7)

Copy Markdown View Source

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 watched
  • pid -- the client connection process
  • deadline_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

cleanup(pid)

@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

count(key)

@spec count(binary()) :: non_neg_integer()

Returns the number of waiters registered for key.

Useful for testing and monitoring.

init()

@spec init() :: :ok

Initializes the waiter ETS table. Must be called once at application start.

notify_push(key)

@spec notify_push(binary()) :: pid() | nil

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

register(key, pid, deadline_ms)

@spec register(binary(), pid(), non_neg_integer()) :: :ok

Registers the calling process as a waiter for key.

Parameters

  • key -- the Redis key to wait on
  • pid -- the client connection process pid
  • deadline_ms -- absolute monotonic deadline in ms (0 = block forever)

Returns

:ok

total_count()

@spec total_count() :: non_neg_integer()

Returns the total number of waiters across all keys.

Useful for testing and monitoring.

unregister(key, pid)

@spec unregister(binary(), pid()) :: :ok

Unregisters a specific waiter for key.

Parameters

  • key -- the Redis key
  • pid -- the client connection process pid