Help us shape the future of Go! Take the 2026 Go Developer Survey

graph

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: May 15, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Пакет graph строит граф зависимостей миграций и выполняет топологическую сортировку. Естественный порядок миграций — лексикографический по Version, объявления `depends-on` переопределяют его. При наличии цикла или висячей зависимости возвращаются типизированные ошибки ErrCycle и ErrDangling.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SelectDownSteps added in v1.0.1

func SelectDownSteps(all []*parser.Migration, applied map[string]bool, appliedByIDDesc []string, n int) ([]*parser.Migration, error)

SelectDownSteps возвращает миграции для команды `down --steps N`: первые N applied-on-disk миграций из appliedByIDDesc плюс каскадно подтянутые applied-on-disk зависимые. Результат — в обратном топологическом порядке (зависимый раньше зависимости).

appliedByIDDesc — список version applied-миграций в порядке убывания id (хронологически: самая поздняя по времени применения первой). Сам граф о store ничего не знает, поэтому порядок передаётся снаружи (раннер строит его из ListApplied).

При n <= 0 возвращается nil без ошибки — валидация >0 живёт выше (CLI/lib). Версии из appliedByIDDesc, которых нет в applied-on-disk (например, applied, но файл удалён), молча пропускаются: раннер обязан проверять «висячие applied» до вызова Select.

Types

type ErrCycle

type ErrCycle struct {
	Versions []string
}

ErrCycle — обнаружен цикл в графе зависимостей. В поле Versions перечислены вершины цикла в направлении рёбер depends-on.

func (*ErrCycle) Error

func (e *ErrCycle) Error() string

type ErrDangling

type ErrDangling struct {
	From    string
	Missing string
}

ErrDangling — миграция From объявляет depends-on на Missing, которой нет среди известных графу узлов.

func Build

func Build(migs []*parser.Migration, applied map[string]bool) ([]*parser.Migration, *ErrDangling, error)

Build строит и валидирует граф, возвращает миграции в топологическом порядке (Кан + тай-брейк лексикографически по Version).

applied — множество версий, уже зафиксированных в schema_migrations (может быть nil). Зависимость считается висячей, если её version нет ни в migs, ни в applied — это соответствует определению из плана.

Миграции с висячими зависимостями (и их транзитивные дети) исключаются из результата, но возвращаются вторым значением — *ErrDangling по первой заблокированной миграции (детерминированно: минимальная version среди заблокированных). err возвращается только для дубликатов и циклов; для висячих зависимостей возвращается dangling != nil и err == nil — вызывающий код может применить безопасное подмножество и потом среагировать на dangling.

func SelectDown

func SelectDown(all []*parser.Migration, applied map[string]bool, toVersion string) ([]*parser.Migration, *ErrDangling, error)

SelectDown возвращает миграции для команды `down`: applied-миграции с Version > toVersion, плюс каскадно подтянутые applied-зависимые (миграции, которые depends-on хоть одну из откатываемых). Всё это — в обратном топологическом порядке (зависимый откатывается раньше зависимости). Пустой toVersion — откатить всё applied.

Каскад нужен для целостности: если миграция A объявляет depends-on B и B попадает под откат, A тоже обязана откатиться, иначе A останется применённой без своей зависимости. Это требование «каскадного отката зависимых» из раздела «Definition of Done» плана.

Миграции, помеченные applied, но отсутствующие в `all`, в каскад не попадают: у них нет DownSQL, и принимать решения за пользователя здесь нельзя. Runner логирует такие случаи отдельным WARN перед запуском.

Down НЕ использует Build(all, applied): тот фильтрует миграции с висячими depends-on (как pending, так и applied), что приводит к двум проблемам: (1) пендинг-миграция со сломанной зависимостью загрязняет результат dangling-ошибкой, не связанной с откатом; (2) applied-миграция с висячей зависимостью исключается из каскада, и её настоящие зависимости можно откатить, оставив её осиротевшей. Поэтому здесь мы строим топологический порядок только над applied-on-disk подмножеством с рёбрами между applied миграциями — edges на non-applied версии считаются удовлетворёнными извне и игнорируются. *ErrDangling всегда nil; параметр сохранён ради симметрии с SelectUp.

func SelectUp

func SelectUp(all []*parser.Migration, applied map[string]bool, toVersion string, logger *slog.Logger) ([]*parser.Migration, *ErrDangling, error)

SelectUp возвращает миграции для команды `up`: pending-миграции с Version <= toVersion, дополненные транзитивными pending-зависимостями (даже если их Version > toVersion — об этом пишется WARN). Результат отсортирован топологически. Пустой toVersion означает «без верхней границы».

Если в графе есть висячие зависимости (определение — см. Build), миграции с такими зависимостями (и их транзитивные потомки) в результат не попадают, а *ErrDangling возвращается вторым значением. Вызывающий код применяет безопасное подмножество, а затем поднимает dangling выше — это поведение «применить всё вплоть до отсутствующей» из спецификации.

func (*ErrDangling) Error

func (e *ErrDangling) Error() string

Jump to

Keyboard shortcuts

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