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
-
AlreadyRegisteredName is already registered by another process.
-
InvalidProcessProcess 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 lookupencoder: Encoder for the message typedecoder: Decoder for the message typetimeout_ms: Maximum time to wait in millisecondspoll_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:
- Extract the Subject(BitArray) from GlobalSubject
- 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 registername: The global name to register undermax_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 registername: The global name to register underpolicy: 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:
- Unregister from global registry
- 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.