dbready

package
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package dbready — ограниченное ожидание готовности Postgres принимать соединения.

Зачем. Init-контейнер `migrate` стартует одновременно с подом Postgres и не ждёт его. Мигратор при этом умирает на ПЕРВОЙ же неудаче (`log.Fatalf`), под уходит в CrashLoopBackOff и «самоизлечивается» только когда PG наконец поднялся. Формально это работает, фактически — шум, который маскирует НАСТОЯЩИЕ сбои старта: в логах и событиях невозможно отличить «PG ещё не успел» от «неверный пароль» / «миграция сломана», потому что обе выглядят одинаково — рестарт.

Что делает пакет. Ждёт ТОЛЬКО класс «БД ещё не принимает соединения» (см. IsNotReady) и ТОЛЬКО в пределах бюджета. Любая другая ошибка возвращается немедленно — конфигурационный дефект обязан падать сразу, а не прятаться под двухминутным ожиданием.

Почему именно Ping, а не «обернуть sql.Open в retry». `sql.Open` ЛЕНИВ: он не дозванивается до сервера и почти никогда не ошибается. Гонка проявляется позже — на первом реальном запросе (у нас это `goose.Up`). Retry вокруг `sql.Open` был бы полностью бесполезен; поэтому барьер ставится явным `PingContext` ДО goose.

Index

Constants

View Source
const (
	// SQLStateCannotConnectNow — 57P03 "the database system is starting up".
	// Канонический признак того, что PG поднялся, но ещё проигрывает WAL.
	SQLStateCannotConnectNow = "57P03"
	// SQLStateAdminShutdown — 57P01, сервер завершается (rolling restart).
	SQLStateAdminShutdown = "57P01"
	// SQLStateCrashShutdown — 57P02, сервер перезапускается после сбоя бэкенда.
	SQLStateCrashShutdown = "57P02"
	// SQLStateTooManyConnections — 53300; на bring-up пул ещё не разошёлся.
	SQLStateTooManyConnections = "53300"
)

SQLState-коды, означающие «сервер жив, но пока не обслуживает» — не путать с ошибками аутентификации/схемы.

View Source
const (
	DefaultInitialInterval = 250 * time.Millisecond
	DefaultMaxInterval     = 5 * time.Second
	DefaultMaxElapsed      = 2 * time.Minute
)

Значения по умолчанию. Бюджет 2 минуты покрывает холодный старт Postgres (initdb + WAL replay) с запасом и при этом ОГРАНИЧЕН: вечно висящий init-контейнер хуже CrashLoopBackOff — он не даёт ни сигнала, ни рестарта.

Variables

This section is empty.

Functions

func IsNotReady

func IsNotReady(err error) bool

IsNotReady сообщает, означает ли ошибка «Postgres ещё не принимает соединения».

Классификация — сердце пакета: false там, где нужно true, вернёт CrashLoopBackOff; true там, где нужно false, спрячет конфигурационный дефект (неверный пароль, несуществующая БД) под таймаутом ожидания. Поэтому список намеренно УЗКИЙ: транспорт (dial/DNS/reset/EOF) + SQLSTATE-класс 08 (connection_exception) + явные «сервер стартует/выключается/перегружен». Всё остальное — включая 28P01 (bad password), 3D000 (no such database), 42501 (no privilege) и любые ошибки самих миграций — настоящая ошибка.

func Wait

func Wait(ctx context.Context, p Pinger, opts Options) error

Wait пингует БД, пока она не начнёт отвечать, но не дольше opts.MaxElapsed.

Возврат:

  • nil — БД принимает соединения;
  • исходная ошибка, если она НЕ из класса «не готов» (fail-fast, без ретраев);
  • ошибка с бюджетом и последней причиной, если БД так и не поднялась;
  • ctx.Err(), если контекст отменён (SIGTERM init-контейнера).

РЕПЛИКИ: запрос — петля принадлежит вызову — ожиданию готовности базы при старте — и завершается по его условию. Ничего не пишет: только опрашивает.

Types

type Options

type Options struct {
	InitialInterval time.Duration
	MaxInterval     time.Duration
	MaxElapsed      time.Duration
}

Options — параметры ожидания. Нулевое значение валидно: каждое поле подставляется дефолтом.

type Pinger

type Pinger interface {
	PingContext(ctx context.Context) error
}

Pinger — минимальный контракт, который реализует *sql.DB. Интерфейс (а не *sql.DB) держит пакет юнит-тестируемым без живого Postgres.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL