transactioncheck
- title
- transactioncheck
- type
- toolbox
- summary
- Go-линтер, находящий вызовы БД через внешний репозиторий вместо дескриптора транзакции
- tags
- golang, static-analysis, databases
- language
- Go
- license
- MIT
- created
- 2026-04-15
- updated
- 2026-09-01
- lang
- ru
- translation_of
- transactioncheck
- source_updated
- 2026-09-01
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Go-линтер, обнаруживающий операции с базой данных, которые утекают за границы транзакции. Написан на базе go-analysis-framework после того, как автор выкатил баг с транзакцией в продакшен - эта история и появление линтера описаны в go-transaction-linter.
Что он находит
В кодовых базах, где транзакции работают через callback'и с паттерном репозитория:
return s.repo.Transaction(ctx, func(tx models.Repo) error {
user, err := s.repo.GetUser(ctx, userID) // FLAGGED: uses s.repo, not tx
return tx.SaveUser(ctx, user)
})
Линтер помечает использование внешнего репозитория (s.repo) внутри callback'ов транзакции, где вместо этого должен использоваться параметр транзакции (tx).
Два типа нарушений:
- Прямые вызовы методов внешнего репозитория
- Передача внешнего репозитория во вспомогательные функции вместо
tx
Как это работает
- Обход AST с фильтрацией по узлам
*ast.CallExpr - Поиск вызовов метода
Transactionу интерфейсов репозитория - Захват параметра callback'а
txкакtypes.Object - Сканирование тела callback'а на предмет обращений к внешнему репозиторию
- Рекурсивный анализ вспомогательных функций, принимающих
tx
Сравнение через types.Object корректно обрабатывает затенение переменных: два идентификатора с одним и тем же объектом указывают на одну и ту же переменную.
Использование
Запуск отдельно:
go install github.com/leonhfr/transactioncheck/cmd/transactioncheck@latest
transactioncheck ./...
Или через задачу mise:
[tasks.transactioncheck]
run = 'bin/transactioncheck ./...'
Тестирование
Использует analysistest с комментариями // want:
_ = s.repo.GetUser( // want "using non-transaction repo..."
ctx, "123",
)
Ограничения
- Требует единообразного именования интерфейсов репозиториев (настраивается)
- Отслеживает нарушения только внутри одного пакета (межпакетный анализ отсутствует)
- Рекурсивный анализ может пропускать нарушения при вызовах через интерфейсы