PropertyDamage.Settle (PropertyDamage v0.2.0)

View Source

Settle logic for eventually consistent systems.

The Settle module provides retry logic for probe and async commands that need to wait for eventual consistency. It supports configurable timeout, interval, and backoff strategies.

Usage

Commands with semantics/0 returning :probe or :async can implement settle_config/0 to customize retry behavior. The Executor uses this module to repeatedly execute the command until it succeeds or times out.

Example

defmodule MyProbe do
  @behaviour PropertyDamage.Command

  def semantics, do: :probe

  def settle_config do
    %{
      timeout_ms: 5_000,
      interval_ms: 200,
      backoff: :exponential
    }
  end
end

Backoff Strategies

  • :linear - Constant interval between retries (default)
  • :exponential - Double the interval after each retry (capped at timeout)

Summary

Functions

Execute a command with settle logic if required.

Get the settle configuration for a command.

Get the execution mode from a command spec map.

Get the semantics of a command.

Get the settle configuration from a command spec map.

Check if a command requires settling (is a probe or async).

Execute a function with settle/retry logic.

Types

settle_result()

@type settle_result() ::
  {:ok, term()}
  | {:settled, term()}
  | {:retry, term()}
  | {:timeout, term()}
  | {:error, term()}

Functions

execute_with_settle(command, execute_fn, opts \\ [])

@spec execute_with_settle(struct(), (-> term()), keyword()) :: term()

Execute a command with settle logic if required.

If the command is a probe or async, wraps execution with settle/retry logic. For regular sync commands, executes directly.

Parameters

  • command - The command struct
  • execute_fn - Function that executes the command, should return settle-compatible result
  • opts - Additional options (merged with command's settle_config)

get_config(command)

@spec get_config(module() | struct() | map()) :: map()

Get the settle configuration for a command.

Returns the command's settle_config if implemented, otherwise returns defaults. Also accepts a command spec map with a :settle key.

get_execution(arg1)

@spec get_execution(map()) :: :sync | :probe | :async

Get the execution mode from a command spec map.

Returns the :execution value from the spec map, or :sync if not present.

get_semantics(command)

@spec get_semantics(module() | struct() | map()) :: :sync | :probe | :async

Get the semantics of a command.

Returns the command's semantics if implemented, otherwise returns :sync (default). Also accepts a command spec map with an :execution key.

get_settle_config(arg1)

@spec get_settle_config(map()) :: map()

Get the settle configuration from a command spec map.

Returns the :settle value from the spec map merged with defaults.

requires_settling?(command)

@spec requires_settling?(module() | struct()) :: boolean()

Check if a command requires settling (is a probe or async).

settle(fun, opts \\ [])

@spec settle(
  (-> settle_result()),
  keyword()
) :: settle_result()

Execute a function with settle/retry logic.

The function should return:

  • {:ok, result} - Success, stop retrying
  • {:settled, result} - Successfully settled, stop retrying
  • {:retry, reason} - Need to retry (will continue until timeout)
  • {:error, reason} - Hard failure, stop retrying immediately

Options

  • :timeout_ms - Maximum time to wait (default: 2000)
  • :interval_ms - Time between retries (default: 300)
  • :backoff - Backoff strategy, :linear or :exponential (default: :linear)

Returns

  • {:ok, result} - Function succeeded
  • {:settled, result} - Function settled successfully
  • {:timeout, last_reason} - Timed out waiting for success
  • {:error, reason} - Function returned hard error