PhoenixKit.TestSupport.PostgresPreflight (phoenix_kit v2.29.1)

Copy Markdown View Source

One bounded, classified PostgreSQL connection attempt, for use from a test_helper.exs.

Why this exists

Every package in this ecosystem defaults its test role to postgres (System.get_env("PGUSER", "postgres")). That default is right for CI and for Debian, and wrong for a Homebrew install, where initdb names the superuser after the OS user and no postgres role exists.

The problem is not the default — it is what a wrong one looks like. These suites run through the Ecto SQL sandbox, so a rejected login does not surface as "authentication failed". DBConnection queues the checkout and retries with backoff, and the run dies minutes later on a pool checkout timeout that reads exactly like a flaky test. That disguise is the defect this module removes, and the only one it claims to.

What a pass does and does not prove

A pass means the endpoint was reachable, TLS and protocol negotiation succeeded, the credentials were accepted, and the target database could be selected. It is a connection preflight, not a "database is ready" check. It says nothing about whether the pool can open all its connections, whether migrations have run, whether the caller has table privileges, or whether sandbox ownership is configured correctly. Those already fail loudly and are deliberately out of scope — do not grow this into a second copy of the repo startup path.

Usage

check/1 never converts a connection problem into a raise, because most suites here degrade to unit-only rather than fail when there is no database:

case PhoenixKit.TestSupport.PostgresPreflight.check(MyApp.Test.Repo) do
  :ok ->
    start_repo_and_migrate()

  {:error, _reason, message} ->
    IO.puts(:stderr, message)
    ExUnit.configure(exclude: [:integration])
end

check!/1 is for a suite that has no meaningful unit-only mode.

Not application code

This ships in lib/ because sibling packages depend on phoenix_kit through Hex, where a test/support directory is unreachable. It follows the precedent of Ecto.Adapters.SQL.Sandbox. Never call it from application code.

Summary

Functions

Attempts one connection. Returns :ok, or {:error, reason, message} with a message safe to print — it names the effective host, port, database and username, and never the password.

check/1, but raises RuntimeError on failure. For a suite with no unit-only mode.

Types

reason()

@type reason() ::
  :auth_rejected
  | :database_not_found
  | :insufficient_privilege
  | :too_many_connections
  | :server_unavailable
  | :unreachable
  | :unknown

Functions

check(repo_or_config)

@spec check(module() | keyword()) :: :ok | {:error, reason(), String.t()}

Attempts one connection. Returns :ok, or {:error, reason, message} with a message safe to print — it names the effective host, port, database and username, and never the password.

Accepts a repo module or a keyword list of repo config.

check!(repo_or_config)

@spec check!(module() | keyword()) :: :ok

check/1, but raises RuntimeError on failure. For a suite with no unit-only mode.