Бэкенд-реализации пока нет. Демо-модуль отображает планируемые потоки на детерминированных моках; содержимое ниже — предлагаемая граница, а не работающая система.
Current
Бэкенд-реализации пока нет: демо отображает детерминированные MSW-сценарии запланированной модели событие → задача → попытки.
Ограниченный пул воркеров с записями по попыткам, экспоненциальный backoff с джиттером, терминальные состояния dead-задач и восстановление брошенной работы на основе аренды (lease).
транзакционное создание задач: inbox → jobs (план)
lease + записи попыток: jobs → worker (план)
отправка + запись результата: worker → provider (план)
Целевой поток уведомлений: события → durable-задачи доставки.
Инженерные решения
Везде at-least-once; дедупликация — ответственность потребителя
Целевой дизайн: брокер и воркеры гарантируют только at-least-once. Inbox дедуплицирует по ID события, а запись результата отправки идемпотентна.
Kafka DLQ и dead-задачи доставки — разные механизмы
Целевой дизайн: DLQ уровня брокера обрабатывает структурно необрабатываемые сообщения; dead-задачи уровня приложения — отклонённые провайдером или постоянно падающие доставки со своими политиками ретраев.
Lease-аренда восстанавливает брошенные задачи
Целевой дизайн: воркер держит lease с ограниченным сроком; при падении lease истекает и задачу подхватывает другой воркер. Дубликаты «отправка удалась, потом падение» решаются идемпотентной записью результата.
Надёжность / сценарии отказа
Дубликаты событий
Один и тот же ID события, доставленный дважды (ретрай брокера, rebalance консьюмера), должен закоммититься в inbox один раз; вторая копия подтверждается как уже обработанная.
Poison-сообщения
Сообщения, постоянно падающие на десериализации или валидации, не должны блокировать партицию: ограниченные ретраи, затем dead-letter с записанной причиной.
Временные против постоянных ошибок провайдера
429/5xx/таймауты ретраятся с backoff и джиттером; 4xx-ошибки валидации провайдера терминальны — задача уходит в dead с сохранённой причиной провайдера.
Успешная отправка, затем падение процесса
Провайдер принял письмо, но воркер умер до записи результата: ретрай даёт дубликат письма. Ограничивается ключами идемпотентности, где провайдер их поддерживает, и честной формулировкой «at-least-once».
Брошенные задачи в processing
Задачи, застрявшие в «processing» после смерти воркера, забираются повторно после истечения lease; число циклов перехвата ограничено до объявления задачи dead.