db

package
v1.5.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: 10 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultSSLMode = "prefer"

DefaultSSLMode — режим, который применяет libpq/pgx, когда DSN вообще не несёт `sslmode`.

View Source
const PoolParamPrefix = "pool_"

PoolParamPrefix — префикс ключей, которые понимает ТОЛЬКО pgxpool. Вне пула (`pgx.Connect`) такой ключ уезжает серверу как неизвестный runtime-параметр, и отказ наступает на ПОДКЛЮЧЕНИИ, а не на сборке строки.

Variables

This section is empty.

Functions

func ConfigurableSSLModes

func ConfigurableSSLModes() []string

ConfigurableSSLModes — режимы, принимаемые настройкой сервиса, в порядке объявления. Шире SecureSSLModes ровно на `disable`: вне боевого режима открытый канал до локальной базы законен.

func NewPool

func NewPool(ctx context.Context, dsn string) (*pgxpool.Pool, error)

NewPool создает pgxpool с server-side таймаутами и проверяет связь с БД (Ping) — fail-fast на старте: при недоступной БД возвращается ошибка, а не «ленивый» пул, который упадет лишь на первом запросе. Таймаут связи контролируется переданным ctx.

Устанавливаемые RuntimeParams (defense-in-depth, независимо от корректности app-side ctx):

  • statement_timeout=30s — потолок исполнения ОДНОГО запроса.
  • idle_in_transaction_session_timeout=60s — потолок «idle-in-transaction» (транзакция открыта, но не исполняет запрос). Дренер держит claim-tx открытой на время applier-вызова (~5s), reconciler.Sweep — на время одного Resolve (~10s, ResolveTimeout). На каждой итерации Sweep сбрасывает idle-таймер statement'ом: ветки Done/Interrupted — через markDoneCAS/ markErrorCAS, а ветки Skip/resolver-error — через явный keep-alive (reconciler.keepClaimAlive: SELECT 1). Поэтому непрерывный idle ограничен одним ResolveTimeout на любой ветке, а не суммой по батчу. 60s даёт запас ~6x над этим потолком и при этом жёстко реапит по-настоящему зависшую tx (минуты), которую app-side ctx проглядел (CGO/DNS-stall, игнорирующий cancel) — иначе она держала бы FOR UPDATE SKIP LOCKED row-locks и блокировала VACUUM (CWE-400).

lock_timeout НЕ выставляется намеренно: ожидание блокировки и так ограничено statement_timeout (30s), а отдельный lock_timeout ввёл бы новый класс ошибки (SQLSTATE 55P03) на путь contended-CAS во всех сервисах, чьи mapRepoErr его не обрабатывают — регрессия без выигрыша сверх statement_timeout.

func NewPoolStatsCollector

func NewPoolStatsCollector(namespace string, poolName string, pool *pgxpool.Pool) prometheus.Collector

NewPoolStatsCollector собирает коллектор состояния пула `pool`.

`namespace` становится префиксом имён (kaname передаёт `kaname`), `poolName` — значением постоянной метки `pool` (`primary`, `replica`), поэтому несколько пулов одного сервиса не сталкиваются.

`pool == nil` допустим и НЕ является ошибкой: композиционный корень, у которого пула нет, регистрирует коллектор так же, как и остальные, а тот не отдаёт ни одной серии. Ронять на этом /metrics всего процесса значило бы гасить диагностику из-за ненастроенной необязательной части.

func PoolParamFromDSN

func PoolParamFromDSN(dsn string) string

PoolParamFromDSN возвращает ИМЯ пулового параметра, найденного в строке подключения, либо пустую строку.

Возвращает ТОЛЬКО имя ключа — никогда саму строку и никакую её часть, кроме имени. Довод тот же, что у SSLModeFromDSN выше: строка собирается через url.UserPassword и НЕСЁТ ПАРОЛЬ БАЗЫ, а результат уходит в отказ старта, то есть в журнал и оператору. Имя ключа отвечает на вопрос «что править», и этого достаточно, чтобы поднять стенд.

Читает КЛЮЧИ, а не подстроку. Подстрочная проверка совпадала бы и на пароле, и на имени базы, где такая последовательность законна, — то есть отказывала бы в старте по содержимому секрета.

Разбирает обе формы, которыми строка приходит в это дерево: URL-форму (`postgres://…?pool_max_conns=4`) и keyword-форму (`host=… pool_max_conns=4`). Если URL не разбирается (спецсимвол в пароле), остаётся скан ключей по разделителям — он судит левую часть токена, поэтому значение под предикат по-прежнему не подпадает.

func SSLModeConfigurable

func SSLModeConfigurable(mode string) bool

SSLModeConfigurable — значение принимается настройкой сервиса.

Пустую строку не принимает: «не задано» — отдельный исход, и решает про него вызывающий (часть сервисов деривит пустое в `disable`, часть берёт режим из сырого URL). Предикат, схлопнувший «не задано» в «принято», лишил бы их этого различения.

func SSLModeFromDSN

func SSLModeFromDSN(dsn string) string

SSLModeFromDSN возвращает sslmode, который реально доезжает до пула.

Читать сырое config-поле недостаточно: часть сервисов держит sslmode прямо в URL (`repository.postgres.url`), часть деривит его в composeDSN/baseDSN (пустое → `disable`), а третьи — комбинируют (raw-URL выигрывает у поля). Единственный честный источник — сама строка, отданная pgxpool.

Возвращает НОРМАЛИЗОВАННЫЙ (lower-case) режим; пустой DSN → пустая строка. Никогда не возвращает ничего, кроме режима — DSN несёт пароль, а результат уходит в лог.

func SSLModeSecure

func SSLModeSecure(mode string) bool

SSLModeSecure — канал до базы шифруется при этом режиме.

Пустая строка НЕ безопасна и это не придирка: пустое поле деривится сервисами в `disable`, а пустой `sslmode` в самой строке подключения означает DefaultSSLMode — оба допускают открытый канал.

func SSLModes

func SSLModes() []string

SSLModes — весь словарь режимов. Нужен распознавателям (гейт дерева `internal/repohygiene`), чтобы искать перечисления по ЖИВОМУ перечню, а не по своей копии: копия у гейта была бы тем же классом, который гейт ловит.

func SecureSSLModes

func SecureSSLModes() []string

SecureSSLModes — режимы, допустимые на БОЕВОЙ посадке, в порядке объявления. Возвращается копия: перечень — правило безопасности, и вызывающий не должен иметь возможности его переписать.

Types

type CeilingReader

type CeilingReader interface {
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}

CeilingReader — узкий порт: ровно один вопрос, который здесь задаётся.

type ConnBudget

type ConnBudget struct {
	// PoolMaxConns — потолок пула ОДНОЙ реплики.
	//
	// Берётся у самого пула (`pool.Config().MaxConns`), а НЕ из настройки:
	// настройка бывает не задана, и тогда действует умолчание драйвера, которое
	// зависит от числа ядер узла. Посадка о нём не знает, а база его получит.
	PoolMaxConns int32

	// Replicas — сколько реплик посадка может поднять ОДНОВРЕМЕННО.
	//
	// Это ПОТОЛОК раскладки, а не текущее число живых подов: проверка отвечает на
	// вопрос «поместится ли посадка целиком», и брать текущее число значило бы
	// признавать годной посадку, которая перестаёт быть годной от собственного
	// штатного роста.
	Replicas int
}

ConnBudget — сколько соединений посадка ОБЕЩАЕТ базе.

func (ConnBudget) Validate

func (b ConnBudget) Validate(c ConnCeiling) error

Validate отвечает, помещается ли обещанное в принимаемое.

Имя — по здешнему обычаю (`Config.Validate`), и оно НЕ `Check`: так зовётся вопрос к хранилищу отношений, и гейт, стерегущий полосы этого вопроса, честно поймал бы одноимённый метод про пул как неучтённое место. Предикат по имени мерит соглашение об именовании — значит соглашение и надо соблюсти.

Незаявленная величина — ОТКАЗ, а не пропуск. Ноль в любом сомножителе обращает произведение в ноль, и проверка проходила бы всегда, ничего не проверив: «не объявлено» стало бы означать «не ограничиваем» — тот же класс, что пустой круг доверенных отправителей, который пропускает всех.

type ConnCeiling

type ConnCeiling struct {
	MaxConnections    int
	SuperuserReserved int
}

ConnCeiling — что база готова принять.

func ReadConnCeiling

func ReadConnCeiling(ctx context.Context, q CeilingReader) (ConnCeiling, error)

ReadConnCeiling спрашивает у базы её собственные пределы.

`current_setting` вместо `SHOW` — чтобы обе величины приехали одним запросом и относились к одному мгновению; читаются они как текст и приводятся здесь, потому что тип настройки в каталоге — строка.

func (ConnCeiling) Available

func (c ConnCeiling) Available() int

Available — слоты, которые база отдаёт обычным клиентам.

Запас суперпользователя вычтен: он существует затем, чтобы к исчерпавшей себя базе можно было подключиться и разобраться. Раздав его службе, мы отнимаем ровно тот доступ, которым чинят последствия.

type Transactor

type Transactor struct {
	// contains filtered or unexported fields
}

Transactor оборачивает pgxpool и предоставляет транзакционный метод InTx.

func NewTransactor

func NewTransactor(p *pgxpool.Pool) *Transactor

NewTransactor создает новый Transactor поверх существующего пула.

func (*Transactor) InTx

func (t *Transactor) InTx(ctx context.Context, fn func(tx pgx.Tx) error) error

InTx запускает fn в транзакции. Если fn возвращает err — транзакция откатывается.

Directories

Path Synopsis
Package pgfault — дом ОДНОГО правила: отказ хранилища, разобранный по классу.
Package pgfault — дом ОДНОГО правила: отказ хранилища, разобранный по классу.

Jump to

Keyboard shortcuts

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