IHOR.DEVБАЗА_ЗНАНЬ
МЕНЮ

~/blog / Розгортання / background-jobs-and-queue-design.md

// посібник · 3 хв читання

Фонові завдання та проєктування черг

Проєктуйте фонові задачі з повторною доставкою, обмеженими спробами й відновленням. Розділяйте прийняття задачі, виконання ефекту та підтвердження черги.

Коротка відповідь

Використовуйте надійну чергу, коли робота має продовжуватися після завершення початкового запиту. Повертайте підтвердження прийняття лише після надійного запису задачі, а worker нехай перевіряє повідомлення, виконує ідемпотентний ефект і підтверджує завершення. Проєктуйте повторну доставку й зупинку worker між ефектом та підтвердженням.

Продукт обробки документів на кшталт PDF.ai є корисним прикладом: прийняття документа, аналіз і доступ до результату мають різні стани завершення. Це не визначає чергу, яку використовує продукт. Асинхронний API має надавати стабільний ідентифікатор задачі й захищений endpoint стану замість твердження про завершення аналізу після постановки в чергу.

Практичні кроки реалізації

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

Визначайте спроби за класом помилки. Тимчасова недоступність сервісу може вимагати відкладеного повтору; некоректні дані потребують виправлення або остаточної відмови. Обмежуйте кількість спроб і час обробки, зберігайте діагностичну причину без чутливих даних і передбачайте явний повтор задач із dead-letter черги. Відстежуйте вік найстарішої задачі й довжину черги.

Приклад реалізації

Ця межа worker явно визначає порядок. Адаптер має реалізувати ідемпотентний ефект у надійному сховищі; інтерфейс не гарантує усунення дублікатів у пам’яті. Помилка залишає повідомлення непідтвердженим, тому черга може доставити його повторно за своїми правилами.

type Job = { id: string; inputKey: string; receipt: string };
type WorkerAdapters = {
  applyIdempotently: (job: Job) => Promise<void>;
  acknowledge: (receipt: string) => Promise<void>;
};

export async function handleJob(job: Job, adapters: WorkerAdapters) {
  await adapters.applyIdempotently(job);
  await adapters.acknowledge(job.receipt);
}

Для ефекту лише в базі забезпечуйте унікальний ключ операції й фіксуйте запис дублювання разом із бізнес-зміною в одній транзакції. Якщо після commit підтвердження черги не вдасться, повторна задача побачить збережений результат. Для зовнішнього платежу чи листа база не може атомарно зафіксувати чужий ефект; використовуйте ключ ідемпотентності провайдера й зберігайте стан для узгодження невизначених результатів.

Компроміси й альтернативи

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

Типові помилки

Уникайте підтвердження до commit, трактування тимчасової невидимості як постійного блокування, нескінченного повтору некоректних задач і використання локального Set як єдиного запису дублікатів. Тайм-аут може означати невідомий результат, а не відсутність ефекту; сліпий повтор може двічі списати кошти чи сповістити.

Контрольний список перед випуском

  • Прийняття підтверджується після надійного запису задачі.
  • Повторна доставка використовує стабільний ключ операції.
  • Підтвердження черги настає після завершення.
  • Тайм-аут видимості й heartbeat відповідають тривалості.
  • Визначено діагностику dead-letter, дозволений повтор і сповіщення черги.

Поширені запитання

Чи запобігає тайм-аут видимості всім дублікатам?

Ні. Використовуйте його для узгодження обробки й відновлення, зберігаючи безпечний ефект повторної доставки.

Чи має API чекати worker?

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

Наступний крок

Зупиніть worker після commit ефекту до підтвердження й повторно доставте задачу. Ефект має відбутися один раз, а завершення — залишатися видимим.

Першоджерела

Пов’язані матеріали й приклади

Ігор Харчишин

Незалежний full-stack інженер продуктів, який пише посібники з реалізації розширень браузера та сучасних вебпродуктів на основі першоджерел.

Потрібно реалізувати це у вашому продукті?

Пов’язана реалізація інтерфейсу, логіки застосунку, API та шару даних.