Flushing Ecto db connections periodically in Elixir

In Elixir’s db_connection library version 2.4.1 and above there is a facility to disconnect all the connections.

The myxql module MyXql.Client do_connect/1 function is what actually translates your “hostname” into an IP address (via gen_tcp.connect/4). By periodically calling disconnect_all/3 all the existing connections are dropped (within the time limit you specify) and do_connect/1 gets called again for each connection so if there has been a DNS change it’ll be picked up.

I wouldn’t try this unless you can identify an obvious problem. The db_connection library is managing some complex things already. You don’t want to add complexity to it if you can avoid it. In any case, here’s some sample code that can do the work.

defmodule Ecto.PeriodicFlush do
  @moduledoc """
  Run a background process to periodically disconnect from databases
  """
  use GenServer

  @flush_interval 30_000

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: opts[:name] || __MODULE__)
  end

  @doc """
  Flush all the connections for a list of Ecto.Repo's
  Flushing connections ensures that our driver does a DNS lookup
  again
  """
  def flush_connections(repos) when is_list(repos) do
    Enum.each(repos, fn repo ->
      %{pid: pid, opts: opts} = Ecto.Adapter.lookup_meta(repo)
      DBConnection.disconnect_all(pid, 15_000, opts)
    end)
  end

  @impl true
  def init(opts) do
    flush_interval = Keyword.get(opts, :flush_interval, @flush_interval)
    repos = Keyword.get(opts, :repos, [])
    schedule_flush(flush_interval)
    {:ok, %{flush_interval: flush_interval, repos: repos}}
  end

  @impl true
  def handle_info(:flush_connections, %{flush_interval: flush_interval, repos: repos} = state) do
    flush_connections(repos)
    schedule_flush(flush_interval)
    {:noreply, state}
  end

  defp schedule_flush(flush_interval) do
    Process.send_after(self(), :flush_connections, flush_interval))
  end
end



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Elixir/OTP Supervision
  • Elixir and Ecto's telemetry events
  • Elixir, Phoenix Framework and Datatables
  • The ex_sleeplock library
  • Elxiir Unit Tests and Iterating a Single Test