singlepass

package
v1.4.0 Latest Latest
Warning

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

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

Documentation

Overview

Package singlepass разводит фоновый проход между репликами: из всех процессов, подошедших к проходу одновременно, его исполняет ровно один.

Предмет

Фоновая работа поднимается в КАЖДОЙ реплике: у процесса нет способа узнать, что он не один. Пока реплика одна, разницы не видно; вторую поднимает автомасштабирование по загрузке — то есть под нагрузкой, когда дублирование дороже всего, и между «работает» и «начало дублировать» нет ни решения человека, ни записи в журнале.

Когда брать замок прохода, а когда клеймить строки

Замок прохода годится там, где проход — БЭКСТОП: он редок, ограничен своим пределом на партию и не обязан ускоряться от числа реплик. Тогда «исполняет один» есть ровно то, что уже написано в комментарии у предела партии, и код с развёртыванием перестают противоречить друг другу.

Он НЕ годится там, где проход — несущий путь материализации: сериализовав его на весь кластер, мы лишили бы работу возможности идти в несколько реплик. Такому проходу нужен КЛЕЙМ СТРОКИ (`FOR UPDATE SKIP LOCKED` либо условная правка-CAS): реплики берут непересекающиеся партии и работают одновременно.

Почему сессионный замок, а не транзакционный

Транзакционный (`pg_advisory_xact_lock`) живёт до конца транзакции, а проход транзакцией не является: он ходит к соседям и в плоскость данных, и держать транзакцию открытой всё это время значило бы занимать соединение и удерживать снимок ради взаимного исключения. Сессионный замок занимает ОДНО соединение пула и снимается закрытием, которое возвращает функция.

Что делает проигравший

НИЧЕГО — и это штатный исход, а не отказ. Проигравший пропускает свой тик и приходит на следующем. Считать это ошибкой значило бы, что N−1 реплик пишут отказ на каждом успешном проходе: наблюдаемость деградирует ровно там, где она нужна.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoPool = errors.New("singlepass: pool is required")

ErrNoPool — проход просят развести, а базы не подали. Отдельная ошибка, а не «взяли и пошли»: молчаливый пропуск замка вернул бы ровно тот дубль, ради которого пакет заведён, и выглядел бы при этом исправной работой.

Functions

This section is empty.

Types

type Release

type Release func(context.Context)

Release снимает замок прохода. Принимает контекст ЯВНО, потому что зовётся из defer, когда контекст прохода уже мог быть отменён.

func TryAcquire

func TryAcquire(ctx context.Context, pool *pgxpool.Pool, name string) (Release, bool, error)

TryAcquire пытается взять именованный замок прохода.

Возвращает (release, true, nil), если проход достался нам; (nil, false, nil), если его уже исполняет другая реплика; ошибку — только на отказе базы.

name — устойчивое имя прохода, а не идентификатор реплики: замок берётся по его хэшу, поэтому два процесса с одним именем встречаются на одном ключе. Пространство ключей — общее для всей базы, поэтому имя обязано нести домен («kacho.compute.stuck-delete-finisher»), а не глагол («sweep»).

Jump to

Keyboard shortcuts

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