Краткий ответ
Фоновая задача должна иметь устойчивую связь с событием, состояния выполнения и ограниченный порядок повторов. Сохранение основной операции отделяют от доставки уведомления, но обеспечивают надёжную постановку задания; ошибки остаются видимыми и допускают безопасную повторную обработку.
Отделите результат операции от уведомления
Заявка может быть успешно сохранена, даже если почтовый сервис временно недоступен. Пользователь должен получать сообщение по факту основного результата, а сотрудник — видеть проблему доставки отдельно. Если приложение хранит обращение только в письме, потеря уведомления становится потерей данных. Начните с определения источника принятой операции.
Обратная ошибка тоже опасна: письмо отправлено, но запись не сохранилась. Системы показывают разные состояния одного действия. Определите, как событие сохранения связано с постановкой фонового задания. Эта связь должна выдерживать остановку процесса между шагами, а не зависеть только от последовательности двух вызовов в коде.
Опишите контракт задания
| Поле или правило | Назначение | Пример проверки |
|---|---|---|
| Идентификатор | Отличить задачу от повтора | Повторная постановка не дублирует эффект |
| Связанный объект | Найти исходную операцию | Заявка существует и доступна исполнителю |
| Версия данных | Определить содержание сообщения | Не отправлена случайно устаревшая версия |
| Состояние | Понять ход выполнения | Ошибка не выглядит завершением |
| Повторы | Ограничить повторную обработку | Постоянная ошибка не крутится бесконечно |
Состояния могут называться по-разному, но должны различать ожидание, выполнение, успех и окончательную неудачу. Укажите владельца зависших задач. Время постановки, начала и завершения позволяет отделить очередь от медленного внешнего сервиса. Одного общего счётчика отправленных писем для диагностики недостаточно.
Обеспечьте постановку после изменения данных
Для важных процессов рассмотрите запись события рядом с основной операцией в одной согласованной транзакционной границе и последующую обработку. Конкретная реализация зависит от хранилища и архитектуры. Цель — не потерять задачу между подтверждением пользователю и обращением к внешней системе. Само наличие брокера сообщений эту границу автоматически не закрывает.
Сохраняйте минимально необходимое содержание. Если обработчик читает актуальные данные позже, определите, допустимо ли изменение объекта до отправки. Если нужен снимок момента события, храните предусмотренную версию. Для чувствительных сведений продумайте область доступа и срок хранения; не копируйте весь объект в каждый журнал по умолчанию.
Настройте повторы по типу ошибки
Временная недоступность допускает повтор с задержкой, а неверный адрес или запрещённая операция требуют исправления. Ограничьте число попыток и срок обработки. При массовом сбое не создавайте бесконечную лавину запросов. Контракт внешнего сервиса и его лимиты определяют допустимый режим восстановления.
Повтор должен учитывать идемпотентность. После потери ответа внешний сервис мог уже выполнить действие. Если он не предоставляет надёжный ключ операции или проверку результата, риск повторного эффекта остаётся и требует отдельного решения. Не обещайте универсальную доставку «ровно один раз» только потому, что очередь хранит одно задание.
Сделайте неудачи доступными оператору
После исчерпания попыток задача попадает в понятную очередь разбора с причиной и связанным объектом. Сотрудник видит, что можно исправить, и кто вправе повторить обработку. Повторный запуск сохраняет историю, а не стирает ошибку. Для необратимых действий может понадобиться дополнительная проверка фактического результата у получателя.
Уведомления об ошибках тоже должны иметь владельца. Если сигнал приходит в неиспользуемый канал, мониторинг не обеспечивает реакции. Связь технического события и доступности команды разобрана в статье о мониторинге и поддержке. Не отправляйте одинаковую тревогу на каждую попытку, если она мешает увидеть причину общего сбоя.
Учебный сценарий потери ответа
Сервис отправляет подтверждение заказа, провайдер принимает запрос, но соединение обрывается до ответа. Обработчик не знает результат. По контракту он проверяет идентификатор операции или повторяет её с тем же ключом, если сервис это поддерживает. Новый случайный ключ может создать второе сообщение и не решить неопределённость первого.
В проверке остановите обработчик после сохранения, после постановки и после внешнего вызова. Сверьте состояния после запуска. Добавьте постоянную ошибку и ручное исправление. У пользователя остаётся одна принятая операция, а оператор способен объяснить судьбу каждой фоновой задачи.
Что передать в эксплуатацию
Нужны показатели задержки, объёма очереди, ошибок и зависших заданий, а также инструкция повторной обработки. Отдельно укажите, какие действия безопасно повторять автоматически. Такой контракт позволяет развивать уведомления и интеграции без превращения каждого временного сбоя в ручное расследование с неизвестным результатом.
Как повторять неудачное задание после исправления данных
Если уведомление не ушло из-за неверного адреса, бесконечные автоматические повторы бесполезны. Заданию нужен понятный статус, причина остановки и разрешённое действие оператора. После исправления входных данных сохраните связь с исходной операцией и историю повторного запуска.
В учебном сценарии оператор запускает доставку дважды. Проверка должна показать, что основной объект не создаётся повторно, а политика повторных уведомлений соблюдается. Уточните, использует повтор старое содержимое или актуальную версию: это важно для счетов и изменившихся условий. Наблюдаемость включает возраст очереди и необработанные ошибки; один показатель «процесс запущен» не подтверждает, что задания доходят до результата.
Термины из материала
Применить к вашему проекту
Спроектируем фоновые процессы так, чтобы заявки, уведомления и повторные попытки оставались управляемыми.
Обсудить задачу