← Назад до блогу

Вправа: побудуйте патерн Transactional Outbox у n8n

Практична редакційна вправа: побудуйте патерн transactional outbox у n8n, щоб подія позначалась доставленою лише після підтвердження цільової системи.

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

Перевірено за наведеними джерелами .

Редакційна вправа: що ви побудуєте і навіщо

Це редакційна вправа: завдання для самостійного відпрацювання у вашому власному середовищі n8n, а не сертифіковане завдання чи воркфлоу, який ми побудували й протестували за вас. Мета — побудувати патерн transactional outbox у n8n так, щоб подія, надіслана до цільової системи, позначалась доставленою лише після того, як ця система справді підтвердить отримання, а не в момент, коли ваш воркфлоу її надсилає.

Ви працюватимете з базою даних Postgres і цільовою системою — HTTP-ендпоінтом або брокером повідомлень, — записуватимете бізнес-запис і запис outbox разом, а потім побудуєте невеликий релей в n8n, який виявляє нові рядки outbox, надсилає їх далі та позначає кожен рядок обробленим лише після підтвердження.

Контекст: проблема подвійного запису і що гарантує патерн transactional outbox

Проблема, яку вирішує цей патерн, відома як проблема подвійного запису (dual-write problem). Воркфлоу потрібно оновити базу даних і повідомити про цю зміну цільову систему, але це дві окремі операції; без розподіленої транзакції одна може виконатися успішно, а інша — ні, і тоді ці дві сторони розійдуться. Патерн transactional outbox уникає цього, записуючи бізнес-запис і запис про подію для надсилання — рядок outbox — в межах однієї й тієї самої транзакції бази даних, тож вони не можуть розійтися самі по собі.

Варто чітко розуміти, що саме це дає. Власні рекомендації n8n щодо цього патерну прямо стверджують, що дублювання доставки завжди можливе, тож насправді ви будуєте надійну, підтверджену доставку «принаймні один раз» (at-least-once), а не буквальну доставку «рівно один раз». Саме тому цей патерн безпечно працює лише разом з ідемпотентним споживачем на іншому кінці — таким, що може отримати одну й ту саму подію двічі, не обробивши її двічі.

Архітектор програмного забезпечення Кріс Річардсон (Chris Richardson) зазначає те саме у власному описі цього патерну, говорячи про сторону споживача в цьому обміні.

Рекомендації n8n також дають просте операційне правило для самого воркфлоу: позначати рядок outbox обробленим лише після того, як доставка справді відбулася успішно, і ніколи раніше. Саме навколо цього правила структуровані кроки побудови нижче.

Sources: Pattern: Transactional outbox, How the Transactional Outbox Pattern Guarantees Event Delivery – n8n Blog

Передумови та вхідні дані

Перш ніж почати, перевірте, чи відповідає ваше налаштування тому, що передбачає ця вправа. Вона розрахована на розробника, який уже впевнено користується вузлом Postgres в n8n і базовою обробкою помилок, а не на перший воркфлоу.

Конкретні вхідні дані — це бізнес-таблиця, яку ви вже маєте або створюєте для цієї вправи, наприклад таблиця замовлень, нова таблиця outbox зі стовпцями для корисного навантаження, прапорця статусу та часової позначки, а також облікові дані, потрібні n8n для доступу як до Postgres, так і до обраної вами цільової системи.

Sources: Postgres | Nodes | n8n Docs, HTTP Request | Nodes | n8n Docs, RabbitMQ | Nodes | n8n Docs

Обмеження

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

Sources: How the Transactional Outbox Pattern Guarantees Event Delivery – n8n Blog, Postgres Trigger | Nodes | n8n Docs, HTTP Request | Nodes | n8n Docs, Handle errors gracefully | Build | n8n Docs, Postgres | Nodes | n8n Docs

Кроки побудови: від атомарного запису до підтвердженої доставки

П'ять етапів релею показують, як патерн transactional outbox переміщує подію від атомарного запису до підтвердженої доставки.
Ілюстративна послідовність кроків побудови вправи, а не знімок реального полотна n8n.

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

Послідовність побудови релею outbox

  1. Записати пару: В одному пакеті транзакції Postgres вставте бізнес-рядок і рядок outbox зі статусом «очікує»; якщо будь-яка вставка провалиться, обидві відкотяться.
  2. Виявити нові рядки: Підхопіть рядок, що очікує, за допомогою вузла Postgres Trigger, який слухає вставки в таблицю outbox.
  3. Опублікувати подію: Надішліть корисне навантаження рядка до цільової системи за допомогою вузла HTTP Request, або передайте його брокеру, наприклад RabbitMQ, за допомогою вузла RabbitMQ в n8n.
  4. Перевірити підтвердження: Розгалузьте за допомогою вузла If залежно від того, чи повернув виклик відповідь 2xx, вважаючи будь-який інший результат недоставленим.
  5. Позначити рядок обробленим: Лише у гілці з підтвердженням оновіть статус рядка outbox на «оброблено» за допомогою вузла Postgres.
  6. Обробити відмову: У гілці без підтвердження використайте вузол Stop and Error, щоб запуск завершився з видимою помилкою, і прикріплений воркфлоу обробки помилок міг сповістити команду.

Обраний спосіб виявлення та цільова система змінюють кілька деталей, але форма патерну transactional outbox лишається незмінною протягом усього процесу: нічого не позначається обробленим, доки цільова система справді не підтвердить це.

Sources: Postgres | Nodes | n8n Docs, How the Transactional Outbox Pattern Guarantees Event Delivery – n8n Blog, Postgres Trigger | Nodes | n8n Docs, RabbitMQ | Nodes | n8n Docs, HTTP Request | Nodes | n8n Docs, If | Nodes | n8n Docs, Handle errors gracefully | Build | n8n Docs

Критерії завершення та усунення несправностей

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

Якщо рядки застряють у статусі «очікує», спершу перевірте два моменти: чи справді опубліковано воркфлоу, адже відповідний тригер бази даних вузла Postgres Trigger існує лише поки це так, і чи справді вузол HTTP Request отримує справжню відповідь 2xx, а не редирект або сторінку помилки, замасковану під успіх.

Sources: Postgres | Nodes | n8n Docs, HTTP Request | Nodes | n8n Docs, How the Transactional Outbox Pattern Guarantees Event Delivery – n8n Blog, Handle errors gracefully | Build | n8n Docs, Postgres Trigger | Nodes | n8n Docs

Рефлексія та ескіз пропонованого рішення

Розумний ескіз рішення: два запити Postgres в одному пакеті транзакції для запису, вузол Postgres Trigger для виявлення, вузол HTTP Request для публікації, вузол If, що перевіряє код статусу, вузол Postgres в гілці успіху, що позначає рядок обробленим, і вузол Stop and Error в гілці відмови, що живить воркфлоу Error Trigger, який сповіщає вас.

Якщо вашою цільовою системою є брокер повідомлень замість HTTP-ендпоінту, замініть вузол HTTP Request і перевірку коду статусу на вузол RabbitMQ в n8n, і оновлюйте рядок outbox лише після того, як отримаєте еквівалентне підтвердження від етапу з брокером.

Це особиста або командна практична вправа, а не готова до продакшену реалізація: наведені вище кроки — це редакційний дизайн, побудований на документованих можливостях n8n. Перш ніж покладатися на цей патерн у спільному продакшн-інстансі, сприймайте його як відправну точку, яку ваша команда адаптує під власну схему, цільову систему та сценарії відмов.

Sources: How the Transactional Outbox Pattern Guarantees Event Delivery – n8n Blog, Postgres Trigger | Nodes | n8n Docs, Postgres | Nodes | n8n Docs, Handle errors gracefully | Build | n8n Docs, HTTP Request | Nodes | n8n Docs, If | Nodes | n8n Docs

Спробуйте на практиці

Практичні завдання з n8n

Оберіть завдання й створіть робочий воркфлоу у власному середовищі n8n – до кожного завдання є п’ять поступових підказок.

Спробувати практичне завдання

Для вашої команди

Програми навчання n8n для однієї команди чи відділу – на вашому власному екземплярі n8n, з вашими інструментами й даними.

Навчання для вашої команди