DoubleEntryLedger.Command.ErrorMap (double_entry_ledger v0.1.0)

View Source

Provides error tracking and management for command processing in the Double Entry Ledger system.

This module defines the ErrorMap struct used to track errors, completed steps, and retry attempts during command processing, particularly when handling Optimistic Concurrency Control (OCC) conflicts.

Structure

The ErrorMap contains:

  • errors: List of error entries, each with a message and timestamp
  • steps_so_far: Map of steps that completed successfully before an error occurred
  • retries: Counter tracking the number of retry attempts made

Key Functions

Usage Examples

Creating an error map:

error_map = ErrorMap.create_error_map(command)

Adding an error:

updated_errors = ErrorMap.build_errors(error_map.errors, "Transaction failed due to stale data")
%{error_map | errors: updated_errors}

Implementation Notes

The ErrorMap is primarily used within the OCC processor to track retry attempts and preserve error contexts when a transaction fails due to concurrent modifications to the same data.

Summary

Types

Represents a single error entry with a message and timestamp.

t()

The ErrorMap structure used for tracking errors during command processing.

Functions

Creates a standardized error entry from various input types.

Adds a new error to the beginning of an existing error list.

Initializes an ErrorMap from a Command or TransactionCommandMap.

Types

error()

@type error() :: %{message: String.t(), inserted_at: DateTime.t()}

Represents a single error entry with a message and timestamp.

Contains details about an error that occurred during command processing.

Fields

  • message: A descriptive message about the error
  • inserted_at: DateTime when the error was recorded

t()

@type t() :: %DoubleEntryLedger.Command.ErrorMap{
  errors: [error()] | [],
  retries: integer(),
  save_on_error: boolean(),
  steps_so_far: map()
}

The ErrorMap structure used for tracking errors during command processing.

This is the main structure for tracking retry attempts, errors, and partial transaction results during optimistic concurrency control processing.

Fields

  • errors: List of error entries, newest first
  • steps_so_far: Map of steps that completed successfully before an error occurred
  • retries: Number of retry attempts that have been made

Functions

build_error(error)

@spec build_error(any()) :: error()

Creates a standardized error entry from various input types.

Converts any error representation into a standardized error map structure with a message and timestamp.

Parameters

  • error: The error to standardize (string or any other type)

Returns

  • A standardized error map with message and timestamp

Examples

iex> alias DoubleEntryLedger.Command.ErrorMap
iex> error = ErrorMap.build_error("Invalid amount")
iex> is_map(error) and is_binary(error.message)
true

iex> alias DoubleEntryLedger.Command.ErrorMap
iex> error = ErrorMap.build_error(%{reason: :not_found})
iex> String.contains?(error.message, "not_found")
true

build_errors(errors, error_message)

@spec build_errors([error()], any()) :: [error()]

Adds a new error to the beginning of an existing error list.

Creates a standardized error entry from the provided message and prepends it to the existing list of errors.

Parameters

  • errors: The existing list of errors
  • error_message: The error message or object to add

Returns

  • The updated list of errors with the new error at the front

Examples

iex> alias DoubleEntryLedger.Command.ErrorMap
iex> errors = []
iex> updated_errors = ErrorMap.build_errors(errors, "Transaction failed")
iex> length(updated_errors)
1

changeset_errors(changeset)

@spec changeset_errors(Ecto.Changeset.t()) :: String.t()

create_error_map(arg1)

Initializes an ErrorMap from a Command or TransactionCommandMap.

Creates a new ErrorMap structure, preserving any existing errors from the command while initializing other tracking fields.

Parameters

  • command: Command or TransactionCommandMap to initialize from

Returns

  • A new ErrorMap struct with initialized fields

Examples

iex> alias DoubleEntryLedger.Command.ErrorMap
iex> alias DoubleEntryLedger.Command
iex> command = %Command{command_queue_item: %{errors: [%{message: "Previous error", inserted_at: ~U[2023-01-01 00:00:00Z]}]}}
iex> error_map = ErrorMap.create_error_map(command)
iex> error_map.retries
0
iex> length(error_map.errors)
1