Lockstep.Registry (Lockstep v0.1.0)

Copy Markdown View Source

Lockstep-aware process registry. Models the most common subset of OTP Registry under Lockstep's controller, so libraries that depend on key-based process lookup work under controlled scheduling.

Supported

  • Unique keys (keys: :unique) and duplicate keys (keys: :duplicate).

  • register/3, unregister/2, lookup/2, dispatch/3, count/1, keys/2.

  • Automatic cleanup on registering-process death (via Lockstep.monitor).

  • :via tuple integration with Lockstep.GenServer:

    via = {:via, Lockstep.Registry, {reg, :my_name}}
    {:ok, _} = Lockstep.GenServer.start_link(MyMod, [], name: via)
    Lockstep.GenServer.call(via, :req)

Not modeled

  • Partitioned registries (partitions: option). Single-partition only.
  • Listeners.
  • match/4 patterns -- only :_ lookup via lookup/2.
  • Meta key/value store (meta/2, put_meta/3).

Most production callers don't depend on the omitted bits; if you need them, file an issue.

Summary

Functions

Number of registered entries across all keys.

Dispatch a callback over every {pid, value} registered under key. The callback may be

Keys registered by pid in reg. Same shape as Registry.keys/2.

Look up entries under key. Returns [{pid, value}] (one entry for unique keys, possibly many for duplicate keys), or [] if no registration.

Read a key-keyed metadata value previously stored via put_meta/3. Returns {:ok, value} if found, :error otherwise. Same shape as OTP Registry.meta/2.

Store metadata under key. Returns :ok. Same shape as OTP Registry.put_meta/3.

Register the calling process under key with value.

Run an ETS match spec against the registry's entries. Each entry is shaped as {key, pid, value}, matching OTP Registry.select/2. Useful for libraries that enumerate all subscribers via Registry.select.

Start a registry. Options

Remove the calling process's registration under key. Always returns :ok (no-op if no such registration).

Types

registry()

@type registry() :: pid()

Functions

count(reg)

@spec count(registry()) :: non_neg_integer()

Number of registered entries across all keys.

dispatch(reg, key, fun)

@spec dispatch(
  registry(),
  any(),
  ([{pid(), any()}] -> any()) | {module(), atom(), [any()]}
) :: :ok

Dispatch a callback over every {pid, value} registered under key. The callback may be:

  • a 1-arity function -- receives [{pid, value}, ...]
  • an {module, function, args} MFA tuple -- invoked as apply(module, function, [entries | args]), matching the shape OTP's Registry.dispatch/4 accepts.

keys(reg, pid)

@spec keys(registry(), pid()) :: [any()]

Keys registered by pid in reg. Same shape as Registry.keys/2.

lookup(reg, key)

@spec lookup(registry(), any()) :: [{pid(), any()}]

Look up entries under key. Returns [{pid, value}] (one entry for unique keys, possibly many for duplicate keys), or [] if no registration.

meta(reg, key)

@spec meta(registry(), any()) :: {:ok, any()} | :error

Read a key-keyed metadata value previously stored via put_meta/3. Returns {:ok, value} if found, :error otherwise. Same shape as OTP Registry.meta/2.

put_meta(reg, key, value)

@spec put_meta(registry(), any(), any()) :: :ok

Store metadata under key. Returns :ok. Same shape as OTP Registry.put_meta/3.

register(reg, key, value)

@spec register(registry(), any(), any()) ::
  {:ok, pid()} | {:error, {:already_registered, pid()}}

Register the calling process under key with value.

For :unique registries returns {:error, {:already_registered, pid}} when the key is taken. :duplicate always succeeds.

select(reg, match_spec)

@spec select(registry(), :ets.match_spec()) :: [any()]

Run an ETS match spec against the registry's entries. Each entry is shaped as {key, pid, value}, matching OTP Registry.select/2. Useful for libraries that enumerate all subscribers via Registry.select.

start_link(opts \\ [])

@spec start_link(keyword()) :: {:ok, pid()}

Start a registry. Options:

  • :keys -- :unique (default) or :duplicate.
  • :name -- accepted for shape compatibility with Registry, but Lockstep does not register the registry itself by name (pass the returned pid around or use :via only on regular Lockstep.GenServers).

unregister(reg, key)

@spec unregister(registry(), any()) :: :ok

Remove the calling process's registration under key. Always returns :ok (no-op if no such registration).