lib/helpers.ex

defmodule NoizuLabs.Entities.Helpers do
  def wait_for_condition(condition, timeout \\ 5_000, options \\ nil)

  def wait_for_condition(condition, timeout, options) do
    reference = make_ref()
    task = Task.async(fn -> wait_loop(condition, reference, options) end)
    result = Task.yield(task, timeout)

    case result do
      :ok ->
        :ok

      {:ok, response} ->
        {:ok, response}

      _ ->
        response =
          receive do
            {:condition_not_met, response} -> {:timeout, response}
            e -> {:timeout, e}
          after
            50 -> {:timeout, :timeout}
          end

        Task.shutdown(task, 0)
        response
    end
  end

  defp wait_loop(condition, reference, options) do
    case condition.() do
      true ->
        :ok

      :ok ->
        :ok

      {:ok, details} ->
        {:ok, details}

      response ->
        send(reference, {:condition_not_met, response})
        :timer.sleep(options[:poll] || 100)
        wait_loop(condition, reference, options)
    end
  end
end