GoodJob.RepoPool (good_job v1.0.0)

Copy Markdown View Source

Database connection pool management for GoodJob.

This module provides utilities for configuring and managing database connection pools for different GoodJob components:

  • Job processing (schedulers, executors)
  • LISTEN/NOTIFY (notifier)
  • Utility operations (cleanup, stats)

Connection Pool Sizing

GoodJob requires database connections for:

  1. Job Processing: 1 connection per scheduler process (max_processes)
  2. LISTEN/NOTIFY: 1 dedicated connection (separate from pool)
  3. Utility Operations: Shared with job processing pool

For External Mode (separate worker process):

# config/prod.exs
config :my_app, MyApp.Repo,
  pool_size: GoodJob.Config.max_processes() + 2  # +2 for utility operations (cleanup, etc.)

For Async Mode (same process as web server):

# config/dev.exs
config :my_app, MyApp.Repo,
  pool_size: web_server_processes + GoodJob.Config.max_processes() + 2

Statement and Lock Timeouts

GoodJob can configure PostgreSQL timeouts to prevent long-running queries from blocking other operations:

# config/prod.exs
config :good_job,
  database_statement_timeout: 30_000,  # 30 seconds
  database_lock_timeout: 5_000          # 5 seconds

These timeouts are set per-connection when the pool is initialized.

Summary

Functions

Applies database configuration (timeouts, pool size) to a repository.

Calculates recommended pool size based on GoodJob configuration.

Returns SQL commands to set timeouts (for use in after_connect).

Calculates total connections needed (including LISTEN/NOTIFY).

Types

postgrex_conn()

@type postgrex_conn() :: %{__struct__: atom()}

Functions

configure_repo(repo)

@spec configure_repo(Ecto.Repo.t()) :: {:ok, keyword()}

Applies database configuration (timeouts, pool size) to a repository.

This should be called during application startup to ensure all connections in the pool have the correct settings.

set_timeouts(conn)

@spec set_timeouts(postgrex_conn()) :: :ok

Returns SQL commands to set timeouts (for use in after_connect).

Use this in your Repo configuration:

config :my_app, MyApp.Repo,
  after_connect: {GoodJob.RepoPool, :set_timeouts}

Or manually:

defmodule MyApp.Repo do
  def init(_type, config) do
    config = Keyword.put(config, :after_connect, fn conn ->
      GoodJob.RepoPool.set_timeouts(conn)
    end)
    {:ok, config}
  end
end

total_connections_needed()

@spec total_connections_needed() :: integer()

Calculates total connections needed (including LISTEN/NOTIFY).

This includes:

  • Job processing pool
  • LISTEN/NOTIFY connection (separate)
  • Utility operations (shared with job processing)