MobDev.Bench.Reconnector (mob_dev v0.3.26)

Copy Markdown View Source

Auto-reconnect logic for the bench's BEAM dist connection.

When a probe says the dist connection has dropped (:alive_epmd_only or :alive_dist_only after an RPC timeout), we want to attempt to reconnect automatically rather than leaving the bench in a stuck state for the rest of the run.

This module is pure logic — no GenServer, no timers. The bench polling loop calls tick/2 once per cycle, which decides whether to attempt a reconnect based on the current reachability and elapsed time since the last attempt. This keeps the reconnect logic testable and lets the caller control the cadence.

Backoff schedule (defaults)

1st attempt: immediate
2nd attempt: 2 s after 1st
3rd attempt: 4 s after 2nd
4th attempt: 8 s after 3rd
Subsequent: 30 s cap

Reset to immediate on a successful reconnect.

Summary

Functions

Returns the backoff (in ms) that applies to the next attempt.

Initialise a reconnector for node with cookie. Optional :max_backoff_ms.

Record that the most recent reconnect attempt succeeded — resets the backoff counter and bumps the total_reconnects counter.

Decide whether the caller should attempt a reconnect right now, given the current probe state and current time. Returns {action, updated_reconnector}.

Types

t()

@type t() :: %MobDev.Bench.Reconnector{
  attempts: non_neg_integer(),
  cookie: atom(),
  last_attempt_ms: integer() | nil,
  max_backoff_ms: pos_integer(),
  node: atom(),
  total_reconnects: non_neg_integer()
}

Functions

current_backoff_ms(reconnector)

@spec current_backoff_ms(t()) :: non_neg_integer()

Returns the backoff (in ms) that applies to the next attempt.

iex> r = MobDev.Bench.Reconnector.new(:node@host, :secret)
iex> MobDev.Bench.Reconnector.current_backoff_ms(r)
0

iex> r = %{MobDev.Bench.Reconnector.new(:node@host, :secret) | attempts: 3}
iex> MobDev.Bench.Reconnector.current_backoff_ms(r)
8000

new(node, cookie, opts \\ [])

@spec new(atom(), atom(), keyword()) :: t()

Initialise a reconnector for node with cookie. Optional :max_backoff_ms.

record_success(r)

@spec record_success(t()) :: t()

Record that the most recent reconnect attempt succeeded — resets the backoff counter and bumps the total_reconnects counter.

tick(reconnector, probe, now_ms)

@spec tick(t(), MobDev.Bench.Probe.t() | atom(), integer()) ::
  {:no_action | :attempt, t()}

Decide whether the caller should attempt a reconnect right now, given the current probe state and current time. Returns {action, updated_reconnector}.

Actions:

  • :no_action — connection is healthy or it's not time yet
  • :attempt — caller should try Node.connect(reconnector.node) now

After a successful reconnect, call record_success/1 to reset the backoff.