singularity

Singularity is a registry for shared singleton actors, in Gleam.

When an actor’s process exits, it will be removed from the registry automatically. Fetching an actor using the require function will block until that actor has been registered. These two properties allow OTP supervisors to start your actors only when their dependencies are ready.

Example Usage

import actor_a
import actor_b

// Define a wrapper type for the actors (Subjects) you want register.
type Actors {
  ActorA(Subject(actor_a.Message))
  ActorB(Subject(actor_b.Message))
}

pub fn main() {
  let assert Ok(registry) = singularity.start()
  let assert Ok(actor_a_subj) = actor_a.start()
  let assert Ok(actor_b_subj) = actor_b.start()

  // Register the actors specifying your wrapper (`Actors`) variant.
  singularity.register(registry, ActorA, actor_a_subj)
  singularity.register(registry, ActorB, actor_b_subj)

  // Retrieve registered actors, each will be returned via your
  // wrapper type.
  let assert ActorA(got_a) =
    singularity.require(registry, ActorA, timeout_ms: 1000)
  let assert ActorB(got_b) =
    singularity.require(registry, ActorB, timeout_ms: 1000)
}

The example above is for illustrative purposes only; it will not compile. Please see the README and tests for concrete examples.

Types

Singularity’s message/Subject type.

pub opaque type Message(wrap)

Functions

pub fn register(
  with actor: Subject(Message(a)),
  key variant: fn(Subject(b)) -> a,
  subject subj: Subject(b),
) -> Subject(b)

Registers an actor, using the actors wrapper type constructor as a key.

Registered actor processes will be monitored. Processes that exit will be removed from the registry automatically.

Returns the subject unchanged, for ease of use in pipelines.

pub fn require(
  from actor: Subject(Message(a)),
  key variant: fn(Subject(b)) -> a,
  timeout_ms timeout: Int,
) -> a

Retrieves an actor, using the actors wrapper type constructor as a key. If the actor is not present in the registry, the request will be retried every 100ms for a total of timeout_ms before crashing.

If your actors need to establish network connections during startup, consider using long (5000ms+) timeouts for them and any actors that depend on them.

pub fn start() -> Result(Subject(Message(a)), StartError)

Starts the registry.

Note: Gleam actors are linked to the parent process by default.

pub fn stop(actor: Subject(Message(a))) -> Nil

Shuts down the registry. Does not affect registered actors.

pub fn try_get(
  from actor: Subject(Message(a)),
  key variant: fn(Subject(b)) -> a,
) -> Result(a, Nil)

Retrieves an actor, using the actors wrapper type constructor as a key. If the actor is not present in the registry, returns None.

Search Document