Documentation
¶
Index ¶
- Constants
- func ConfigurableSSLModes() []string
- func NewPool(ctx context.Context, dsn string) (*pgxpool.Pool, error)
- func NewPoolStatsCollector(namespace string, poolName string, pool *pgxpool.Pool) prometheus.Collector
- func PoolParamFromDSN(dsn string) string
- func SSLModeConfigurable(mode string) bool
- func SSLModeFromDSN(dsn string) string
- func SSLModeSecure(mode string) bool
- func SSLModes() []string
- func SecureSSLModes() []string
- type CeilingReader
- type ConnBudget
- type ConnCeiling
- type Transactor
Constants ¶
const DefaultSSLMode = "prefer"
DefaultSSLMode — режим, который применяет libpq/pgx, когда DSN вообще не несёт `sslmode`.
const PoolParamPrefix = "pool_"
PoolParamPrefix — префикс ключей, которые понимает ТОЛЬКО pgxpool. Вне пула (`pgx.Connect`) такой ключ уезжает серверу как неизвестный runtime-параметр, и отказ наступает на ПОДКЛЮЧЕНИИ, а не на сборке строки.
Variables ¶
This section is empty.
Functions ¶
func ConfigurableSSLModes ¶
func ConfigurableSSLModes() []string
ConfigurableSSLModes — режимы, принимаемые настройкой сервиса, в порядке объявления. Шире SecureSSLModes ровно на `disable`: вне боевого режима открытый канал до локальной базы законен.
func NewPool ¶
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 ¶
PoolParamFromDSN возвращает ИМЯ пулового параметра, найденного в строке подключения, либо пустую строку.
Возвращает ТОЛЬКО имя ключа — никогда саму строку и никакую её часть, кроме имени. Довод тот же, что у SSLModeFromDSN выше: строка собирается через url.UserPassword и НЕСЁТ ПАРОЛЬ БАЗЫ, а результат уходит в отказ старта, то есть в журнал и оператору. Имя ключа отвечает на вопрос «что править», и этого достаточно, чтобы поднять стенд.
Читает КЛЮЧИ, а не подстроку. Подстрочная проверка совпадала бы и на пароле, и на имени базы, где такая последовательность законна, — то есть отказывала бы в старте по содержимому секрета.
Разбирает обе формы, которыми строка приходит в это дерево: URL-форму (`postgres://…?pool_max_conns=4`) и keyword-форму (`host=… pool_max_conns=4`). Если URL не разбирается (спецсимвол в пароле), остаётся скан ключей по разделителям — он судит левую часть токена, поэтому значение под предикат по-прежнему не подпадает.
func SSLModeConfigurable ¶
SSLModeConfigurable — значение принимается настройкой сервиса.
Пустую строку не принимает: «не задано» — отдельный исход, и решает про него вызывающий (часть сервисов деривит пустое в `disable`, часть берёт режим из сырого URL). Предикат, схлопнувший «не задано» в «принято», лишил бы их этого различения.
func SSLModeFromDSN ¶
SSLModeFromDSN возвращает sslmode, который реально доезжает до пула.
Читать сырое config-поле недостаточно: часть сервисов держит sslmode прямо в URL (`repository.postgres.url`), часть деривит его в composeDSN/baseDSN (пустое → `disable`), а третьи — комбинируют (raw-URL выигрывает у поля). Единственный честный источник — сама строка, отданная pgxpool.
Возвращает НОРМАЛИЗОВАННЫЙ (lower-case) режим; пустой DSN → пустая строка. Никогда не возвращает ничего, кроме режима — DSN несёт пароль, а результат уходит в лог.
func SSLModeSecure ¶
SSLModeSecure — канал до базы шифруется при этом режиме.
Пустая строка НЕ безопасна и это не придирка: пустое поле деривится сервисами в `disable`, а пустой `sslmode` в самой строке подключения означает DefaultSSLMode — оба допускают открытый канал.
func SSLModes ¶
func SSLModes() []string
SSLModes — весь словарь режимов. Нужен распознавателям (гейт дерева `internal/repohygiene`), чтобы искать перечисления по ЖИВОМУ перечню, а не по своей копии: копия у гейта была бы тем же классом, который гейт ловит.
func SecureSSLModes ¶
func SecureSSLModes() []string
SecureSSLModes — режимы, допустимые на БОЕВОЙ посадке, в порядке объявления. Возвращается копия: перечень — правило безопасности, и вызывающий не должен иметь возможности его переписать.
Types ¶
type CeilingReader ¶
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 ¶
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 поверх существующего пула.