Jido.Util (Jido v2.0.0-rc.1)

View Source

A collection of utility functions for the Jido framework.

This module provides various helper functions that are used throughout the Jido framework, including:

  • ID generation
  • Name validation
  • Error handling
  • Logging utilities

These utilities are designed to support common operations and maintain consistency across the Jido ecosystem. They encapsulate frequently used patterns and provide a centralized location for shared functionality.

Many of the functions in this module are used internally by other Jido modules, but they can also be useful for developers building applications with Jido.

Summary

Functions

Conditionally logs a message based on comparing threshold and message log levels.

Generates a unique ID.

Converts a string to a binary.

Validates that all modules in a list implement the Jido.Action behavior. Used as a custom validator for NimbleOptions.

Validates that a module is a valid Elixir module that can be loaded. Used as a custom validator for NimbleOptions.

Validates that a module is a valid Elixir module that can be compiled. Used as a custom validator for NimbleOptions that handles compilation order.

Validates the name of a Action.

Creates a via tuple for process registration with a registry.

Finds a process by name, pid, or {name, registry} tuple.

Types

server()

@type server() ::
  pid() | atom() | binary() | {name :: atom() | binary(), registry :: module()}

Functions

cond_log(threshold_level, message_level, message, opts \\ [])

@spec cond_log(Logger.level(), Logger.level(), Logger.message(), keyword()) :: :ok

Conditionally logs a message based on comparing threshold and message log levels.

This function provides a way to conditionally log messages by comparing a threshold level against the message's intended log level. The message will only be logged if the threshold level is less than or equal to the message level.

Parameters

  • threshold_level: The minimum log level threshold (e.g. :debug, :info, etc)
  • message_level: The log level for this specific message
  • message: The message to potentially log
  • opts: Additional options passed to Logger.log/3

Returns

  • :ok in all cases

Examples

# Will log since :info >= :info
iex> cond_log(:info, :info, "test message")
:ok

# Won't log since :info > :debug
iex> cond_log(:info, :debug, "test message")
:ok

# Will log since :debug <= :info
iex> cond_log(:debug, :info, "test message")
:ok

generate_id()

@spec generate_id() :: String.t()

Generates a unique ID.

string_to_binary!(string)

@spec string_to_binary!(String.t()) :: binary()

Converts a string to a binary.

validate_actions(actions, opts \\ [])

@spec validate_actions(
  [module()] | module(),
  keyword()
) :: :ok | {:ok, [module()] | module()} | {:error, String.t()}

Validates that all modules in a list implement the Jido.Action behavior. Used as a custom validator for NimbleOptions.

This function ensures that all provided modules are valid Jido.Action implementations by checking that they:

  1. Are valid Elixir modules that can be loaded
  2. Export the required action_metadata/0 function that indicates Jido.Action behavior

Parameters

  • actions: A list of module atoms or a single module atom to validate

Returns

  • {:ok, actions} if all modules are valid Jido.Action implementations
  • {:error, reason} if any module is invalid

Examples

iex> defmodule ValidAction do
...>   use Jido.Action,
...>     name: "valid_action"
...> end
...> Jido.Util.validate_actions([ValidAction])
{:ok, [ValidAction]}

iex> Jido.Util.validate_actions([InvalidModule])
{:error, "All actions must implement the Jido.Action behavior"}

# Single module validation
iex> Jido.Util.validate_actions(ValidAction)
{:ok, [ValidAction]}

validate_module(module)

@spec validate_module(any()) :: {:ok, module()} | {:error, String.t()}

Validates that a module is a valid Elixir module that can be loaded. Used as a custom validator for NimbleOptions.

Parameters

  • module: A module atom to validate

Returns

  • {:ok, module} if the module is valid
  • {:error, reason} if the module is invalid

Examples

iex> Jido.Util.validate_module(Enum)
{:ok, Enum}

iex> Jido.Util.validate_module(:invalid_module)
{:error, "Module :invalid_module does not exist or cannot be loaded"}

validate_module_compiled(module)

@spec validate_module_compiled(any()) :: {:ok, module()} | {:error, String.t()}

Validates that a module is a valid Elixir module that can be compiled. Used as a custom validator for NimbleOptions that handles compilation order.

Uses Code.ensure_compiled/1 which blocks until the module finishes compilation or returns an error, making it safe for parallel compilation scenarios.

Parameters

  • module - The module atom to validate

Returns

  • {:ok, module} if the module can be compiled
  • {:error, reason} if the module is invalid or cannot be compiled

Examples

iex> Jido.Util.validate_module_compiled(Enum)
{:ok, Enum}

iex> Jido.Util.validate_module_compiled(:invalid_module)
{:error, "Module :invalid_module does not exist or could not be compiled"}

validate_name(name, opts \\ [])

@spec validate_name(
  any(),
  keyword()
) :: :ok | {:error, String.t()}

Validates the name of a Action.

The name must contain only letters, numbers, and underscores.

Parameters

  • name: The name to validate.

Returns

  • {:ok, name} if the name is valid.
  • {:error, reason} if the name is invalid.

Examples

iex> Jido.Action.validate_name("valid_name_123")
{:ok, "valid_name_123"}

iex> Jido.Action.validate_name("invalid-name")
{:error, "The name must contain only letters, numbers, and underscores."}

via_tuple(name_or_tuple, opts \\ [])

@spec via_tuple(
  server(),
  keyword()
) :: {:via, Registry, {module(), String.t()}}

Creates a via tuple for process registration with a registry.

Parameters

  • name: The name to register (atom, string, or {name, registry} tuple)
  • opts: Options list
    • :registry - The registry module to use (required when not using tuple form)

Returns

A via tuple for use with process registration

Examples

iex> Jido.Util.via_tuple({:my_process, MyApp.Jido.Registry})
{:via, Registry, {MyApp.Jido.Registry, "my_process"}}

iex> Jido.Util.via_tuple(:my_process, registry: MyApp.Jido.Registry)
{:via, Registry, {MyApp.Jido.Registry, "my_process"}}

whereis(server, opts \\ [])

@spec whereis(
  server(),
  keyword()
) :: {:ok, pid()} | {:error, :not_found}

Finds a process by name, pid, or {name, registry} tuple.

Parameters

  • server: The process identifier (pid, name, or {name, registry} tuple)
  • opts: Options list
    • :registry - The registry module to use (required when not using tuple form)

Returns

  • {:ok, pid} if process is found
  • {:error, :not_found} if process is not found

Examples

iex> Jido.Util.whereis(pid)
{:ok, #PID<0.123.0>}

iex> Jido.Util.whereis({:my_process, MyApp.Jido.Registry})
{:ok, #PID<0.125.0>}

iex> Jido.Util.whereis(:my_process, registry: MyApp.Jido.Registry)
{:ok, #PID<0.124.0>}