PaperTiger.ChaosCoordinator (PaperTiger v1.0.2)

Copy Markdown View Source

Unified chaos testing infrastructure for PaperTiger.

Consolidates all chaos testing capabilities into a single coordinator:

  • Payment chaos (failure rates, decline codes)
  • Event chaos (out-of-order delivery, duplicates, delays)
  • API chaos (timeouts, rate limits, server errors)

Configuration

PaperTiger.ChaosCoordinator.configure(%{
  payment: %{
    failure_rate: 0.1,
    decline_codes: [:card_declined, :insufficient_funds],
    decline_weights: %{card_declined: 0.7, insufficient_funds: 0.3}
  },
  events: %{
    out_of_order: true,
    duplicate_rate: 0.05,
    buffer_window_ms: 500
  },
  api: %{
    timeout_rate: 0.02,
    timeout_ms: 5000,
    rate_limit_rate: 0.01,
    error_rate: 0.01
  }
})

Per-Customer Overrides

# Force specific customer to always fail
PaperTiger.ChaosCoordinator.simulate_failure("cus_xxx", :card_declined)

# Clear override
PaperTiger.ChaosCoordinator.clear_simulation("cus_xxx")

Namespace Isolation

Uses ETS with namespace isolation for test concurrency. Each test process can have its own chaos state.

Summary

Functions

Returns all available decline codes.

Returns a specification to start this module under a supervisor.

Cleans up after chaos testing.

Clears any payment simulation for a customer.

Configures chaos settings. Merges with existing config.

Returns the default decline codes.

Forces all buffered events to be delivered immediately.

Gets the current chaos configuration.

Gets chaos statistics.

Queues an event for potential chaos processing.

Resets all chaos configuration to defaults and clears all state.

Determines if an API request should fail or return a custom response.

Determines if a payment should fail for the given customer.

Forces payment failures for a specific customer.

Starts the ChaosCoordinator.

Functions

all_decline_codes()

Returns all available decline codes.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

cleanup()

@spec cleanup() :: :ok

Cleans up after chaos testing.

This resets chaos configuration AND flushes all Paper Tiger stores to remove any test data that was created during chaos testing. Call this after chaos testing to prevent test data from being synced to the host application's database.

Example

# After running chaos tests
PaperTiger.ChaosCoordinator.cleanup()

clear_simulation(customer_id)

@spec clear_simulation(String.t()) :: :ok

Clears any payment simulation for a customer.

configure(config)

@spec configure(map()) :: :ok

Configures chaos settings. Merges with existing config.

Examples

# Enable payment chaos
configure(%{payment: %{failure_rate: 0.1}})

# Enable event chaos
configure(%{events: %{out_of_order: true, buffer_window_ms: 500}})

# Enable API chaos
configure(%{api: %{timeout_rate: 0.05}})

default_decline_codes()

Returns the default decline codes.

flush_events()

@spec flush_events() :: :ok

Forces all buffered events to be delivered immediately.

Useful in tests to ensure events are processed before assertions.

get_config()

@spec get_config() :: map()

Gets the current chaos configuration.

get_stats()

@spec get_stats() :: map()

Gets chaos statistics.

queue_event(event, deliver_fn)

@spec queue_event(map(), function()) :: :ok

Queues an event for potential chaos processing.

If event chaos is configured, the event may be:

  • Buffered and delivered out of order
  • Duplicated
  • Delayed

If no event chaos is configured, delivers immediately.

reset()

@spec reset() :: :ok

Resets all chaos configuration to defaults and clears all state.

should_api_fail?(path)

@spec should_api_fail?(String.t()) ::
  :ok
  | {:timeout, non_neg_integer()}
  | :rate_limit
  | :server_error
  | {:custom_response, pos_integer(), map()}

Determines if an API request should fail or return a custom response.

Returns:

  • :ok - Request should proceed normally
  • {:timeout, ms} - Request should timeout after sleeping
  • :rate_limit - Request should return 429
  • :server_error - Request should return 500/502/503
  • {:custom_response, status, body} - Return a custom JSON response

Custom Response Example

PaperTiger.ChaosCoordinator.configure(%{
  api: %{
    endpoint_overrides: %{
      "/v1/subscriptions" => {:custom_response, 200, %{"id" => "sub_1", "status" => "past_due"}}
    }
  }
})

should_payment_fail?(customer_id)

@spec should_payment_fail?(String.t()) :: {:ok, :succeed} | {:ok, {:fail, atom()}}

Determines if a payment should fail for the given customer.

Checks customer overrides first, then applies configured chaos rules.

Returns:

  • {:ok, :succeed} - Payment should succeed
  • {:ok, {:fail, decline_code}} - Payment should fail with the given code

simulate_failure(customer_id, decline_code)

@spec simulate_failure(String.t(), atom()) :: :ok

Forces payment failures for a specific customer.

The customer's payments will fail with the given decline code until cleared.

start_link(opts \\ [])

Starts the ChaosCoordinator.