Очереди, потоки, события
Капстоун очередей: собери pipeline обработки заказов
Читать про двойные списания, рехешированные партиции и заполняющие диск slot — не то же самое, что собрать pipeline, который их переживает. Подними реальный pipeline обработки заказов — outbox, Kafka, CDC, consumer groups, DLQ и честный UI — затем намеренно урони каждый хоп и докажи, что система остаётся корректной. Это весь трек, собранный и проверенный на прочность.
Преврати каждый урок трека в одну работающую систему и один failure-drill: сделай запись атомарной, отправляй события at-least-once, ключуй для порядка по заказу, делай dedup на каждом консьюмере, отправляй poison-сообщения в карантин, говори UI правду и инструментируй швы — затем урони каждый хоп и покажи, что инвариант держится.
Спроектируй и собери end-to-end pipeline обработки заказов, который размещает заказ, разветвляет его на консьюмеры оплаты / склада / уведомлений, переживает краш на каждом хопе без двойного списания и без потери записи, отправляет poison-сообщения в карантин и показывает клиенту честный pending-then-confirmed UI — доказывая каждую гарантию намеренным failure-drill'ом, а не только happy-path демонстрацией.
- Диаграмма шести хопов (запись, публикация, маршрутизация, обработка, карантин, отображение) с подписью гарантии и защиты на каждом, совпадающая с тем, что реально делает твой код.
- Drill краша-до-коммита на консьюмере оплаты даёт ровно одно списание на один заказ — продемонстрировано логом запросов шлюза, а не утверждением.
- Poison-сообщение исчерпывает retry-бюджет и появляется в DLQ, пока остаток партиции продолжает течь; живой consumer lag не растёт без предела.
- Залипание CDC-консьюмера триггерит алерт на slot lag до того, как диск primary под угрозой, и max_slot_wal_keep_size задан так, что убежавший slot инвалидируется, а не фатален.
- UI показывает заказ как pending немедленно, никогда преждевременный успех, и сверяется до реального состояния; рефетч во время окна согласованности не стирает собственный заказ пользователя.
- Описание на одну страницу: где живёт каждая гарантия доставки, почему идемпотентность — несущий инвариант, и какие сбои твоя observability поймала бы в production.
- Добавь job сверки для клиента, который ищет заказы, застрявшие в pending дольше дедлайна, и разрешает их по авторитетному состоянию — закрывая разрыв бесконечного спиннера / потерянного подтверждения.
- Добавь exactly-once-в-Kafka на стороне CDC (Kafka-транзакции) и докажи, что это всё равно требует идемпотентных консьюмеров end-to-end, переиграв из DLQ.
- Введи перекос горячего ключа (один кит-клиент) и покажи, что он пинит одну партицию; смягчи на уровне ключа (соли или раздели горячую сущность), а не добавлением партиций.
- Добавь вторую реализацию relay и A/B-drill: гоняй polling и CDC бок о бок, сравни end-to-end задержку и нагрузку на БД при одинаковом темпе заказов и запиши, когда каждый — правильный выбор.
- Добавь runbook: триаж по четырём gauges (lag, глубина DLQ, e2e задержка, slot lag), частые причины каждого, порядок приоритета фиксов и чеклист верификации после фикса.
Это система, которую ты реально проектируешь на ревью: атомарная запись outbox, at-least-once relay (polling, затем CDC), на который ты алертишь и который capишь, топики, ключуемые для порядка по заказу, идемпотентные консьюмеры, коммитящие после обработки, retry-бюджет, ведущий в DLQ для poison-сообщений, честный pending-then-confirmed UI и observability, проштампованная на каждом шве. Failure-drill — это и есть суть: happy-path покажет кто угодно, но senior доказывает инвариант, роняя каждый хоп и показывая, что один заказ всё равно даёт одно списание, одно poison-сообщение отправлено в карантин, а не размножено, и один залипший slot поднимает кого-то до того, как заполнит диск. Собери это один раз end-to-end, и production-версия станет чеклистом вместо инцидента.