Nestjs та TypeORM: Транзакційна база даних

текст перекладу
Користувацький декоратор для багаторазового оброблення транзакцій бази даних

Застосунок обробляє помилки при внесенні змін або додаванні даних, не пошкоджуючи існуючі дані та не зберігаючи нові дані. Наприклад, якщо стався збій API для покупок, дані про покупку не повинні бути збережені.

Що робити?

Щоб ефективно обробляти помилки при внесенні змін або додаванні даних без руйнування існуючих даних або збереження нових, можна впровадити кілька стратегій у вашому застосунку. Мета — гарантувати, що будь-які помилки, які виникають під час процесу зміни даних, будуть правильно оброблені, і система залишатиметься в консистентному стані. Одним із таких варіантів є транзакційна база даних.

Як реалізувати в Nestjs та TypeORM?

У NestJS використання TypeORM для взаємодії з базами даних є дуже поширеним. TypeORM — це ORM (Object-Relational Mapping), який дозволяє працювати з SQL базами даних (такими як PostgreSQL, MySQL, SQLite тощо) за допомогою об'єктів JavaScript/TypeScript.
Припустимо, у нас є такі таблиці:

pic

Приклад таблиці

Тепер ми можемо створити транзакційну базу даних за допомогою TypeORM у NestJS для збереження даних про покупку таким чином:

pic

Перший приклад коду

З прикладу вище частина, що має кольорову позначку, є основним кодом для збереження даних про покупку, тоді як інший код відповідає за початок, коміт, відкат у разі помилки та звільнення транзакційної бази даних.

У чому проблема?

Вищенаведений код уже можна використовувати для виконання транзакцій з базою даних, але що робити, якщо потрібно більше ніж 1 транзакцію, наприклад, для внесення змін до даних при додаванні елементів або продуктів, тоді потрібно ще один метод для їхнього збереження.

Чи доведеться знову писати код для початку, коміту, відкату у разі помилки та звільнення транзакційної бази даних? Хіба це не менш ефективно? Адже ми повинні зосереджуватися лише на основному коді зберігання!

Рішення

Nestjs і TypeORM підтримують мову TypeScript, де ми можемо створити декоратор. Тому ми можемо створити декоратор для обробки початку, коміту, відкату у разі помилки та звільнення транзакційної бази даних, який використовує менеджера сутностей (Entity Manager) з TypeORM, що вже підтримує транзакційність, і який можна інжектувати за допомогою функції Inject в Nestjs.

Ми також додаємо логи при початку транзакції, коміті, лише для читання або коли виникає помилка, і можемо вибирати, яку базу даних використовувати, якщо ми використовуємо більше ніж 1 базу даних. Також можна налаштувати рівень ізоляції.

Ось приклад простого коду користувацького декоратора:

pic

Опція декоратора

pic

Основний код декоратора

Як це реалізувати?

Ми можемо використовувати це для рефакторингу першого коду, додавши @Transactional({option}) з параметром опції. Тоді в методі ми можемо інжектувати менеджера сутностей і використовувати його, як зазвичай, без необхідності думати про те, чи сталася помилка та чи потрібно робити відкат або коміт вручну.

Ось приклад:

pic

Рефакторинг першого коду

Висновок

Ми бачимо, що після створення декоратора один раз, ми можемо повторно його використовувати, і отриманий код стає більш лаконічним, виглядає краще, і, звичайно, відсутній код "шаблонів" (boilerplate).

Ми можемо зосередитися на основному коді, не думаючи про початок, коміт, відкат у разі помилки та звільнення транзакційної бази даних. Також ми можемо бачити логи й контролювати, яку базу даних використовуємо, її рівень ізоляції, навіть встановити параметр "тільки для читання" (readonly) в true, якщо ми не хочемо комітити зміни даних.

Також ми можемо реалізувати декоратор з іншим фреймворком, крім NestJS, якщо розуміємо, як інжектувати DataSource.

Перекладено з: Nestjs & TypeORM Transactional Database

Leave a Reply

Your email address will not be published. Required fields are marked *