Storage and State Management

Copy Markdown View Source

Malla provides several mechanisms for managing state, from ephemeral service-specific data to node-wide configuration and process registration.

Service Storage (ETS)

Each Malla service instance is automatically provided with its own dedicated ETS table for storing runtime data. This storage is ephemeral: it is created when the service starts and is destroyed when the service stops.

This is ideal for use cases like:

  • Caching processed results.
  • Tracking request counts or other metrics.
  • Storing temporary session data or workflow state.

The Malla.Service module provides a simple API for this key-value store.

# Store data for a specific service
Malla.Service.put(MyService, :my_key, "some_value")

# Retrieve the data
value = Malla.Service.get(MyService, :my_key, "default")
# => "some_value"

# Delete the data
Malla.Service.del(MyService, :my_key)

Process Registry

For registering and looking up named processes, Malla provides the Malla.Registry module. It offers two types of registries: one for unique names and one that allows multiple processes to be registered under the same key.

Unique Process Registration

This is useful for singleton processes, like a worker that should only have one instance running. You can use Malla.Registry.via/1 to easily name a GenServer.

# Register a GenServer with a unique name
GenServer.start_link(MyWorker, [], name: Malla.Registry.via("my_unique_worker"))

# Look up the process later
pid = Malla.Registry.whereis("my_unique_worker")

If you try to register another process with the same name, you will get an {:error, {:already_registered, pid}} tuple.

Duplicate Process Registration (Store)

This allows you to register multiple processes under the same key, which is useful for managing pools of workers.

# A worker registers itself on start
def MyWorker.init(id) do
  Malla.Registry.store(:my_worker_pool, %{worker_id: id})
  {:ok, %{id: id}}
end

# Find all registered workers
workers = Malla.Registry.values(:my_worker_pool)
# => [{#PID<...>, %{worker_id: 1}}, {#PID<...>, %{worker_id: 2}}]

Global Configuration Store

For node-wide configuration that needs to be accessed by multiple services or other parts of your application, you can use Malla.Config. This is an ETS-based store that survives service restarts but is local to each node (i.e., it is not distributed).

# Store a global setting
Malla.Config.put(:my_app, :api_key, "secret_key")

# Retrieve the setting from anywhere on the same node
key = Malla.Config.get(:my_app, :api_key)

The storage mechanisms mentioned above are not persistent and will lose their data if the node is restarted. For durable state, you must use an external persistence strategy.