Documentation
¶
Overview ¶
Пакет store — внутренняя обёртка над *sql.DB для работы с таблицей состояния schema_migrations и advisory lock'ом. Не входит в публичный API библиотеки.
Index ¶
- Constants
- Variables
- type AppliedMigration
- type LockHandle
- type Store
- func (s *Store) AcquireLock(ctx context.Context) (*LockHandle, error)
- func (s *Store) Apply(ctx context.Context, m *parser.Migration, appliedBy string) error
- func (s *Store) EnsureSchema(ctx context.Context) error
- func (s *Store) ListApplied(ctx context.Context) ([]AppliedMigration, error)
- func (s *Store) MarkChecksumMismatch(ctx context.Context, version string) error
- func (s *Store) Revert(ctx context.Context, m *parser.Migration) error
Constants ¶
const ( StatusApplied = "applied" StatusChecksumMismatch = "checksum_mismatch" )
Возможные значения колонки status в schema_migrations.
const Table = "schema_migrations"
Table — имя таблицы состояния. Хардкодится по спецификации, не выносится в конфиг.
Variables ¶
var ErrLockBusy = errors.New("gomigr advisory lock is busy: another instance is running")
ErrLockBusy возвращается, если pg_try_advisory_lock не смог взять lock — другой процесс gomigr уже работает с этой БД.
Functions ¶
This section is empty.
Types ¶
type AppliedMigration ¶
type AppliedMigration struct {
ID int64
Version string
Name string
Checksum string
Status string
AppliedBy string
AppliedAt time.Time
}
AppliedMigration — одна строка таблицы schema_migrations.
type LockHandle ¶
type LockHandle struct {
// contains filtered or unexported fields
}
LockHandle хранит выделенное соединение, на котором висит advisory lock. Lock — сессионный, поэтому снимать его обязана та же сессия (то же *sql.Conn).
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store оборачивает уже открытый *sql.DB. Владелец *sql.DB — фасад gomigr, store не открывает и не закрывает соединение самостоятельно.
func (*Store) AcquireLock ¶
func (s *Store) AcquireLock(ctx context.Context) (*LockHandle, error)
AcquireLock пытается взять pg_try_advisory_lock без блокировки. Если lock занят — возвращает ErrLockBusy. При успехе занимает одно соединение из пула до вызова Release.
func (*Store) Apply ¶
Apply выполняет UpSQL миграции и INSERT в schema_migrations в одной транзакции. При любой ошибке транзакция откатывается, миграция считается неприменённой.
func (*Store) EnsureSchema ¶
EnsureSchema создаёт таблицу schema_migrations при отсутствии. Идемпотентен. Для уже существующей таблицы (созданной старой версией библиотеки без колонки id) добавляет колонку id и переномеровывает существующие строки в хронологическом порядке по applied_at (а не в порядке heap-scan, который PostgreSQL использует по умолчанию при заполнении BIGSERIAL и который мог быть перемешан UPDATE-ами над status в MarkChecksumMismatch). Существование колонки сначала проверяется read-only запросом, поэтому ALTER TABLE с ACCESS EXCLUSIVE lock берётся только один раз при апгрейде старой БД, а не на каждый вызов New (включая status).
Сам апгрейд (ALTER + переномеровка + setval) выполняется внутри одной транзакции под pg_advisory_xact_lock: атомарность защищает от ситуации, когда процесс упал между ALTER и UPDATE и БД осталась бы с колонкой id, заполненной heap-порядком (повторный запуск увидел бы hasID=true и больше не починил бы строки). Advisory lock сериализует параллельные первые запуски на легаси-БД — без него два процесса могли бы оба пройти fast-path hasID-проверку и второй упал бы на "column id already exists".
func (*Store) ListApplied ¶
func (s *Store) ListApplied(ctx context.Context) ([]AppliedMigration, error)
ListApplied возвращает все строки schema_migrations, упорядоченные по id (хронологический порядок применения миграций).
func (*Store) MarkChecksumMismatch ¶
MarkChecksumMismatch обновляет статус строки на checksum_mismatch. Используется, когда checksum файла отличается от сохранённого в БД.