Raxol.Architecture.CQRS.CommandHandler behaviour (Raxol v2.0.1)

View Source

Command handler behaviour for CQRS pattern implementation in Raxol.

Command handlers are responsible for processing commands and executing the business logic associated with write operations. Each handler should focus on a single command type and maintain consistency.

Handler Design Principles

  1. Single Responsibility: One handler per command type
  2. Business Logic Focus: Contain domain logic, not infrastructure concerns
  3. Idempotent: Handlers should be safe to retry
  4. Event Generation: Generate domain events for state changes
  5. Error Handling: Provide meaningful error messages

Usage

defmodule MyApp.Handlers.CreateUserHandler do
  use Raxol.Architecture.CQRS.CommandHandler

  alias MyApp.Commands.CreateUserCommand
  alias MyApp.Events.UserCreatedEvent
  alias MyApp.Repositories.UserRepository

  @impl true
  def handle(%CreateUserCommand{} = command, context) do
    with {:ok, user} <- UserRepository.create(command),
         {:ok, event} <- create_user_created_event(user, command),
         :ok <- publish_event(event, context) do
      {:ok, %{user_id: user.id, status: :created}}
    else
      {:error, :user_already_exists} ->
        {:error, :user_already_exists}
      {:error, reason} ->
        {:error, {:user_creation_failed, reason}}
    end
  end

  defp create_user_created_event(user, command) do
    event = %UserCreatedEvent{
      user_id: user.id,
      name: user.name,
      email: user.email,
      created_by: command.created_by,
      correlation_id: command.correlation_id
    }
    {:ok, event}
  end
end

Summary

Functions

Adds command handling middleware.

Creates a command handler context with metadata.

Creates a command handling pipeline.

Creates a CRUD command handler pattern.

Creates a standardized error response.

Executes compensating actions for command failures.

Creates a saga command handler for distributed transactions.

Creates a standardized success response.

Validates command handler requirements.

Validates command preconditions.

Applies optimistic locking to prevent concurrent modifications.

Wraps a function with transaction support.

Types

command()

@type command() :: struct()

context()

@type context() :: map()

result()

@type result() :: {:ok, term()} | {:error, term()}

Callbacks

handle(command, context)

@callback handle(command(), context()) :: result()

Functions

add_middleware(handler_fn, middleware_fns)

Adds command handling middleware.

create_context(command, opts \\ [])

Creates a command handler context with metadata.

create_pipeline(steps)

Creates a command handling pipeline.

crud_handler(repo, entity_module)

Creates a CRUD command handler pattern.

error_response(error_type, details \\ nil)

Creates a standardized error response.

execute_compensation(compensations, context)

Executes compensating actions for command failures.

saga_handler(saga_steps)

Creates a saga command handler for distributed transactions.

success_response(data \\ nil)

Creates a standardized success response.

validate_handler(handler_module)

Validates command handler requirements.

validate_preconditions(command, preconditions)

Validates command preconditions.

with_optimistic_lock(resource, expected_version, update_fn)

Applies optimistic locking to prevent concurrent modifications.

with_transaction(repo, fun)

Wraps a function with transaction support.