ExESDBGater.MessageHelpers (ex_esdb_gater v0.8.0)
Common utilities for ExESDBGater message creation, validation, and handling.
This module provides consistent patterns for all message modules to ensure:
- Proper node field tracking
- Standardized timestamp handling
- Message validation
- Consistent defaults and patterns
Node Field Guidelines
All message structs should include a node-related field that tracks where the event originated:
:node
- for general events originating on a node:originating_node
- for cluster events where distinction is needed from affected nodes:reporting_node
- for metrics/monitoring events where the reporter may differ from the source
Usage
# In message creation functions
def my_message(arg1, arg2, opts \ []) do
%MyMessage{
arg1: arg1,
arg2: arg2,
node: MessageHelpers.get_node(opts),
timestamp: MessageHelpers.current_timestamp()
}
end
# Validate message has required fields
MessageHelpers.validate_message_fields(message, [:node, :timestamp])
Summary
Functions
Extracts cluster context information for enhanced message tracking.
Returns the current timestamp with millisecond precision in UTC.
Ensures consistent metadata structure across all messages.
Creates a unique identifier for messages that need tracking.
Gets the node value from options, defaulting to Node.self().
Gets the originating_node value from options, defaulting to Node.self().
Gets the reporting_node value from options, defaulting to Node.self().
Common validation for all message structs.
Validates that a message struct has all required fields.
Validates that all node-related fields in a message are atoms.
Functions
Extracts cluster context information for enhanced message tracking.
This provides additional context that can be useful for debugging and monitoring in distributed environments.
Returns
A map containing:
:node_name
- Current node name:connected_nodes
- List of connected nodes:cluster_size
- Number of nodes in cluster:node_type
- Derived node type (if determinable)
Returns the current timestamp with millisecond precision in UTC.
This ensures consistent timestamp formatting across all message types.
Ensures consistent metadata structure across all messages.
Merges provided metadata with standard cluster context information.
Examples
iex> MessageHelpers.enrich_metadata(%{custom: "value"})
%{
custom: "value",
cluster_context: %{node_name: :node@host, cluster_size: 3, ...}
}
Creates a unique identifier for messages that need tracking.
Generates a short, URL-safe identifier that includes timestamp info for better traceability.
Gets the node value from options, defaulting to Node.self().
Examples
iex> MessageHelpers.get_node([])
:"node@hostname"
iex> MessageHelpers.get_node([node: :test_node])
:test_node
Gets the originating_node value from options, defaulting to Node.self().
Used for cluster membership and similar events where the originating node needs to be distinguished from affected nodes.
Gets the reporting_node value from options, defaulting to Node.self().
Used for metrics and monitoring events where the reporting node may be different from the event source.
Common validation for all message structs.
This is a comprehensive validation that checks:
- Required fields are present
- Node fields are valid atoms
- Timestamp is a valid DateTime
Usage in message modules
def validate(%MyMessage{} = message) do
MessageHelpers.validate_common(message, [:field1, :field2])
end
Validates that a message struct has all required fields.
Parameters
message
- The message struct to validaterequired_fields
- List of atoms representing required field names
Examples
iex> message = %MyMessage{node: :test, timestamp: DateTime.utc_now()}
iex> MessageHelpers.validate_message_fields(message, [:node, :timestamp])
{:ok, message}
iex> message = %MyMessage{timestamp: DateTime.utc_now()}
iex> MessageHelpers.validate_message_fields(message, [:node, :timestamp])
{:error, {:missing_fields, [:node]}}
Validates that all node-related fields in a message are atoms.
Examples
iex> message = %{node: :test_node, originating_node: :origin}
iex> MessageHelpers.validate_node_fields(message)
:ok
iex> message = %{node: "invalid_node"}
iex> MessageHelpers.validate_node_fields(message)
{:error, {:invalid_node_fields, [:node]}}