glyn/registry

Glyn Registry - Type-Safe Distributed Process Registry

This module provides a type-safe wrapper around Erlang’s syn process registry, enabling distributed service discovery and direct process communication with compile-time type safety.

Actor Integration Pattern

The registry works seamlessly with Gleam’s actor system and composes with PubSub:

import gleam/otp/actor
import glyn/pubsub

pub type ActorMessage {
  CommandMessage(Command)      // Direct commands via Registry
  PubSubMessage(Event)         // Events via PubSub
  ActorShutdown
}

fn start_integration_actor(
  registry: registry.Registry(Command, String),
  pubsub: pubsub.PubSub(Event),
) -> Result(actor.Started(Subject(ActorMessage)), actor.StartError) {
  actor.new_with_initialiser(5000, fn(subject) {
    // Create command subject for Registry
    let command_subject = process.new_subject()
    let assert Ok(_registration) = registry.register(
      registry, "my_service", command_subject, "service_metadata"
    )

    // Subscribe to PubSub events
    let event_subscription = pubsub.subscribe(pubsub, "events", process.self())

    // Compose both message sources
    let selector =
      process.new_selector()
      |> process.select(subject)
      |> process.select_map(command_subject, CommandMessage)
      |> process.select_map(event_subscription.subject, PubSubMessage)

    actor.initialised(initial_state)
    |> actor.selecting(selector)
    |> actor.returning(subject)
    |> Ok
  })
  |> actor.on_message(handle_message)
  |> actor.start()
}

Types

Registration handle for cleanup

pub type Registration(message, metadata) {
  Registration(
    registry: Registry(message, metadata),
    name: String,
    subject: process.Subject(message),
    metadata: metadata,
  )
}

Constructors

  • Registration(
      registry: Registry(message, metadata),
      name: String,
      subject: process.Subject(message),
      metadata: metadata,
    )

Type-safe process registry wrapper

pub opaque type Registry(message, metadata)

Values

pub fn call(
  registry: Registry(message, metadata),
  name: String,
  waiting timeout: Int,
  sending message_fn: fn(process.Subject(reply)) -> message,
) -> Result(reply, String)

Call a registered process and wait for a reply, similar to actor.call

pub fn lookup(
  registry: Registry(message, metadata),
  name: String,
) -> Result(#(process.Subject(message), metadata), String)

Look up a registered process and return a type-safe Subject with metadata

pub fn new(
  scope scope: String,
  message_type message_type: glyn.MessageType(message),
) -> Registry(message, metadata)

Create a new Registry system for a given scope The message_type should be a MessageType that uniquely identifies the message type

pub fn register(
  registry: Registry(message, metadata),
  name: String,
  subject: process.Subject(message),
  metadata: metadata,
) -> Result(Registration(message, metadata), String)

Register a process with a name using a caller-supplied Subject Note: Registration will replace any existing registration with the same name

pub fn send(
  registry: Registry(message, metadata),
  name: String,
  message: message,
) -> Result(Nil, String)

Send a type-safe message to a registered process

pub fn unregister(
  registration: Registration(message, metadata),
) -> Result(Nil, String)

Unregister a process

Search Document