View Source Moar.Retry (Moar v1.19.3)

Retryable functions.

These functions are particularly useful in higher-level tests, though they can be used for any kind of waiting.

See also the retry Hex package.

One use of rescue_for/3 in a test is to wait until an assertion succeeds:

# wait up to 5 seconds for the element with ID "status" to be "finished"
Moar.Retry.rescue_for!(5000, fn ->
  assert view |> element("#status") |> render() == "finished"
end)

One use of retry_for/3 in a test is to wait until something changes before making an assertion:

Moar.Retry.retry_for(5000, fn ->
  view |> element("#status") |> render() == "finished"
end)

assert view |> element("#total") |> render() == "8,675,309"

Link to this section Summary

Functions

Run fun every interval_ms until it doesn't raise an exception. If timeout expires, the exception will be re-raised.

Run fun every interval_ms until it doesn't raise an exception. If the current time reaches expiry, the exception will be re-raised.

Run fun every interval_ms until it returns a truthy value, returning {:ok, <value>}. If timeout expires, returns {:error, :timeout}.

Run fun every interval_ms until it returns a truthy value, returning {:ok, <value>}. If the current time reaches expiry, returns {:error, :timeout}.

Link to this section Functions

Link to this function

rescue_for!(timeout, fun, interval_ms \\ 100)

View Source
@spec rescue_for!(pos_integer() | Moar.Duration.t(), (() -> any()), pos_integer()) ::
  any() | no_return()

Run fun every interval_ms until it doesn't raise an exception. If timeout expires, the exception will be re-raised.

  • timeout can be an integer in milliseconds or a Moar.Duration tuple
iex> Moar.Retry.rescue_for!(20, fn -> raise "always fails" end, 2)
** (RuntimeError) always fails

iex> Moar.Retry.rescue_for!({20, :millisecond}, fn -> raise "always fails" end, 2)
** (RuntimeError) always fails
Link to this function

rescue_until!(expiry, fun, interval_ms \\ 100)

View Source
@spec rescue_until!(DateTime.t(), (() -> any()), pos_integer()) :: any() | no_return()

Run fun every interval_ms until it doesn't raise an exception. If the current time reaches expiry, the exception will be re-raised.

iex> date_time = DateTime.add(DateTime.utc_now(), 20, :millisecond)
iex> Moar.Retry.rescue_until!(date_time, fn -> raise "always fails" end, 2)
** (RuntimeError) always fails
Link to this function

retry_for(timeout, fun, interval_ms \\ 100)

View Source
@spec retry_for(pos_integer() | Moar.Duration.t(), (... -> any()), pos_integer()) ::
  {:ok, any()} | {:error, :timeout}

Run fun every interval_ms until it returns a truthy value, returning {:ok, <value>}. If timeout expires, returns {:error, :timeout}.

  • timeout can be an integer in milliseconds or a Moar.Duration tuple
iex> Moar.Retry.retry_for(20, fn -> 10 end, 2)
{:ok, 10}

iex> Moar.Retry.retry_for(20, fn -> false end, 2)
{:error, :timeout}
Link to this function

retry_until(expiry, fun, interval_ms \\ 100)

View Source
@spec retry_until(DateTime.t(), (... -> any()), pos_integer()) ::
  {:ok, any()} | {:error, :timeout}

Run fun every interval_ms until it returns a truthy value, returning {:ok, <value>}. If the current time reaches expiry, returns {:error, :timeout}.

iex> date_time = DateTime.add(DateTime.utc_now(), 20, :millisecond)
iex> Moar.Retry.retry_until(date_time, fn -> false end, 2)
{:error, :timeout}