distribute/registry

Types

Re-export Pid from gleam/erlang/process for API compatibility. Use gleam/erlang/process.Pid directly in new code.

pub type Pid =
  process.Pid
pub type RegisterError {
  AlreadyRegistered
  InvalidProcess
  InvalidName(String)
  NetworkError(String)
  RegisterFailed(String)
}

Constructors

  • AlreadyRegistered

    Name is already registered by another process.

  • InvalidProcess

    Process is not alive or invalid.

  • InvalidName(String)

    Name contains invalid characters or is too long.

  • NetworkError(String)

    Network partition or connectivity issue.

  • RegisterFailed(String)

    Generic registration failure.

Values

pub fn is_registered(name: String) -> Bool

Check if a name is currently registered.

This is more efficient than whereis when you only need to check existence without creating a Subject.

pub fn lookup_global(
  name: String,
  encoder: fn(msg) -> Result(BitArray, codec.EncodeError),
  decoder: fn(BitArray) -> Result(msg, codec.DecodeError),
) -> Result(global.GlobalSubject(msg), Nil)

Lookup a GlobalSubject by name (async-friendly version).

This is a convenience wrapper that simplifies the common pattern of looking up a GlobalSubject with encoder/decoder.

Example:

case lookup_global("my-service", my_encoder(), my_decoder()) {
  Ok(service) -> global.send(service, MyMessage)
  Error(_) -> io.println("Service not found")
}
pub fn lookup_subject(
  name: String,
) -> Result(process.Subject(msg), Nil)

Retrieve a stored Subject by name.

Returns the exact Subject that was stored with store_subject, preserving the original tag. This allows proper message routing for OTP actors.

Returns Error(Nil) if no Subject is stored under this name.

pub fn lookup_with_timeout(
  name: String,
  encoder: fn(msg) -> Result(BitArray, codec.EncodeError),
  decoder: fn(BitArray) -> Result(msg, codec.DecodeError),
  timeout_ms: Int,
  poll_interval_ms: Int,
) -> Result(global.GlobalSubject(msg), Nil)

Synchronous lookup with timeout.

Attempts to lookup a GlobalSubject, retrying until found or timeout. Useful when waiting for a service to become available.

Parameters:

  • name: The global name to lookup
  • encoder: Encoder for the message type
  • decoder: Decoder for the message type
  • timeout_ms: Maximum time to wait in milliseconds
  • poll_interval_ms: Time between lookup attempts in milliseconds

Returns Ok(GlobalSubject) if found, Error(Nil) on timeout.

pub fn register(
  name: String,
  pid: process.Pid,
) -> Result(Nil, RegisterError)

Register a process globally under the given name.

pub fn register_global(
  global_subject: global.GlobalSubject(msg),
  name: String,
) -> Result(Nil, RegisterError)

Try to register a GlobalSubject, automatically extracting its underlying Subject.

This is a convenience wrapper that combines the most common pattern:

  1. Extract the Subject(BitArray) from GlobalSubject
  2. Register it using register_typed

Example:

let global_subject = actor.start_typed_actor(init, loop, encoder, decoder)
register_global(global_subject, "my-service")
pub fn register_subject(
  name: String,
  subject: process.Subject(a),
) -> Result(Nil, RegisterError)

Deprecated: Use register_typed instead

Register a Subject globally (alias for register_typed).

pub fn register_typed(
  name: String,
  subject: process.Subject(msg),
) -> Result(Nil, RegisterError)

Register a typed Subject globally.

This registers the owner Pid of the subject.

Recommended: Use global.GlobalSubject and register it with this function. The GlobalSubject pattern ensures type-safe messaging with encoder/decoder.

For GlobalSubject: Create with global.new(encoder, decoder), then register with register_typed(name, global.subject(global_subject)).

For custom Subject: Works but requires clients to know the message format.

pub fn register_with_retry(
  global_subject: global.GlobalSubject(msg),
  name: String,
  max_retries: Int,
  retry_delay_ms: Int,
) -> Result(Nil, RegisterError)

Deprecated: Use register_with_strategy with retry.RetryPolicy instead

Synchronous registration with simple retry logic.

DEPRECATED: Use register_with_strategy with a retry policy instead. This function uses fixed delays which can cause thundering herd problems.

Attempts to register a GlobalSubject, retrying up to max_retries times if network errors occur. Useful in distributed environments with transient connectivity issues.

Parameters:

  • global_subject: The GlobalSubject to register
  • name: The global name to register under
  • max_retries: Maximum number of retry attempts (default: 3)
  • retry_delay_ms: Delay between retries in milliseconds (default: 100)

Returns Ok(Nil) on success, Error(RegisterError) if all retries fail.

pub fn register_with_strategy(
  global_subject: global.GlobalSubject(msg),
  name: String,
  policy: retry.RetryPolicy,
) -> Result(Nil, RegisterError)

Synchronous registration with retry logic and exponential backoff.

Attempts to register a GlobalSubject using the provided retry policy. This is the recommended method for production use as it supports exponential backoff and jitter to prevent thundering herd problems.

Parameters:

  • global_subject: The GlobalSubject to register
  • name: The global name to register under
  • policy: Retry policy with backoff configuration

Example:

import distribute/retry

// Recommended: exponential backoff with jitter
let policy = retry.default_with_jitter()
registry.register_with_strategy(subject, "my-service", policy)

// Custom policy for critical services
let critical_policy = retry.aggressive()
  |> retry.with_max_attempts(10)
registry.register_with_strategy(subject, "critical-service", critical_policy)

Returns Ok(Nil) on success, Error(RegisterError) if all retries fail.

pub fn remove_stored_subject(name: String) -> Nil

Remove a stored Subject by name.

This removes the Subject from persistent_term storage. Note that this does NOT unregister the process from Erlang’s global registry - use unregister for that.

pub fn store_subject(
  name: String,
  subject: process.Subject(msg),
) -> Result(Nil, RegisterError)

Store a complete Subject by name.

Unlike register_typed which only stores the Pid in Erlang’s global registry, this function stores the entire Subject including its unique tag. This is essential for OTP actors where the tag is used for message pattern matching.

Use this when you need to retrieve the exact same Subject later, for example when implementing singleton actors that need to be looked up by name.

The Subject is stored using persistent_term which is optimized for read-heavy, rarely-changing data.

pub fn unregister(name: String) -> Result(Nil, RegisterError)

Unregister a globally registered name.

pub fn unregister_and_remove(
  name: String,
) -> Result(Nil, RegisterError)

Unregister and remove stored subject in one call.

Convenience wrapper that combines:

  1. Unregister from global registry
  2. Remove from persistent_term storage

Useful for complete cleanup of a named actor.

pub fn whereis(name: String) -> Result(process.Pid, Nil)

Look up a globally registered process by name. Returns Ok(pid) if found, Error(Nil) otherwise.

pub fn whereis_global(
  name: String,
  encoder: fn(msg) -> Result(BitArray, codec.EncodeError),
  decoder: fn(BitArray) -> Result(msg, codec.DecodeError),
) -> Result(global.GlobalSubject(msg), Nil)

Look up a globally registered GlobalSubject (RECOMMENDED).

This is the type-safe way to lookup distributed processes. Returns a GlobalSubject that enforces encoder/decoder usage.

On success, returns a GlobalSubject that can send/receive typed messages. On error, returns Error(Nil) if the name is not registered.

pub fn whereis_typed(
  name: String,
) -> Result(process.Subject(msg), Nil)

Deprecated: Use whereis_global for GlobalSubject or whereis_with_tag for custom actors

Look up a globally registered process and return a typed Subject with Nil tag.

⚠️ DEPRECATED: Use whereis_global for GlobalSubject or whereis_with_tag for standard actors where you know the tag.

The returned Subject has a Nil tag and won’t work with standard gleam_otp actors.

pub fn whereis_with_tag(
  name: String,
  tag: dynamic.Dynamic,
) -> Result(process.Subject(msg), Nil)

Look up a globally registered process with explicit tag.

Use this when you know the tag of the remote process (e.g., for custom actors). For GlobalSubject, use whereis_global instead (recommended).

The tag parameter should match the tag used by the remote actor. For most cases with Nil tags, use dynamic.nil() as the tag.

Search Document