Pull to refresh

Comments 8

Хорошая идея, особенно с оберткой InTransaction, взял на вооружение.

Не так давно решал такую же проблему, контекст тоже рассматривал. Для меня стояла задача сохранить чистые от транзакций репозитории. Чтоб они не знали с чем работают, транзакция это или просто соединение с базой.

В итоге с помощью дженериков сделал композитор, который оборачивает репозиторий и при вызове транзакции создает его, передав вместо db tx. В итоге все получилось, однако есть проблема в том что этот подход был реализован только для одного репозитория.

После вашей статьи захотелось развить свое решение для поддержки нескольких репозиториев, если получится напишу статью.

Спасибо!

Спасибо большое за фидбек. Честно скажу, о подходе Unit of Work я узнал позже. Он показался мне интересным, но особого профита для своего проекта я не увидел.

Как мне кажется, в таком случае use case должен принимать именно Unit of Work вместо репозиториев. И лучше не смешивать подходы, когда одни use case принимают репозитории, а другие unit of work, то есть всё должно быть в одном стиле.

Хранить в контексте ничего не надо, это нехорошо :-(

Надо просто каждую CRUD операцию написать по 2 раза, без передачи транзакции и с передачей.
(первая вызывает вторую)
Кому не надо знать про БД вызывают первую функцию,
а кому хочется трнзакцию вызывают вторую функцию :-)

// Read - находит запись в БД по ID
func (crud Crud_DB) Read(m *banks.Bank) error { }

// Read_ctx - находит запись в БД по ID
func Read_ctx(ctx context.Context, db postgres_pgx.IConnectionTransaction, m *banks.Bank) error { }

Про хранение в контексте, написал в статье) Буду благодарен полному примеру либо ссылки где можно почитать.

Спасибо что разобрали не только саму реализацию, но и костыли. Интересно было бы увидеть пример с unit of work

context.Value для меня - только read-only request-scoped вещи: дедлайн, trace-id, кто залогинен. Транзакция не из этого списка. Это не значение, а живой ресурс с жизненным циклом (open/commit/rollback), и именно на этой границе подход начинает тихо гнить: компилятор перестаёт помогать, а промах молчаливый - передал исходный ctx вместо txCtx, запись ушла в пул, тест зелёный.
У меня в рукописном http-клиенте была ровно эта развилка с выбором апстрима/провайдера. Я сознательно оставил выбор явным параметром, а в контексте держал только отмену - как раз чтобы не заводить невидимую зависимость, которую не видно в сигнатуре и которая ломается молча. Дороже по многословности, зато забытый аргумент - это ошибка компиляции, а не расхождение в проде.
Поэтому для меня вопрос не ExtractDB vs ExtractTx, а глубже: stateful-ресурс вообще не стоит гонять через context.Value. Транзакция это ресурс. Если её хочется протащить неявно, это чаще сигнал, что граница транзакции живёт не там, где нарисована.

Мне не нравится gorm и передача транзакции в контексте - был негативный опыт. И потому имхо будет именно про это.
Gorm хорош на старте, когда запросы только в одну таблицу. Когда хочется писать sql в несколько таблиц, то в итоге это превращается в sql-over-gorm. И этот геморрой при том, что сейчас писать чистый sql легко и приятно - goland даже умеет проверять поля. Я юзаю sqlx, который умеет парсить ответ в структуры. И планирую перейти на pgx, который умеет в postgres лучше других. То есть вообще считаю gorm ненужным.

Я таки понимаю, что у вас не просто много таблиц, но и множество баз - может вам для этого gorm. Но тут я сторонник разделения кода - лучше копипаста, чем универсальные методы.

Уверен, что передача транзакции в контексте - тупиковый путь. Контекст - для управления. А если источник данные - это параметр, то должен быть в аргументах. Я пишу функциями, куда база или транзакция входит аргументом. Тут в "бонусной части" описал подробнее https://habr.com/ru/articles/992396/

ИМХО, даже если вы решаете какую-то сложную задачу с разными базами и разными транзакциями (точно сложнее моей), то это не обосновывает передачу важных аргументов через контекст. Напишите какую-нить сагу, которая вряд ли будет проще, но потомки будут вам благодарны.

спасибо, почитаю

Напишите какую-нить сагу, которая вряд ли будет проще

сага решает проблему распределенных транзакций, тут все транзакций в рамках одной БД

Sign up to leave a comment.

Articles