Перейти к содержанию

Практикум: сбой Kafka и разбор накопившейся очереди

Сценарий сбоя из статьи. Нужен работающий Docker. Выполните команду из docs/blog/lab/2026-09-07-when-kafka-is-down в клоне репозитория:

uv run --no-project --python 3.13 --with-requirements requirements.txt kafka_down_lab.py

Скрипт импортирует код приложения и запуск контейнеров из практикума по доставке; соседняя директория должна быть на месте. В зависимостях закреплены omni-box 0.3.0, aiokafka 0.14.0, SQLAlchemy 2.0.54, asyncpg 0.31.0 и testcontainers 4.15.0. Скрипт создаёт и удаляет postgres:17-alpine и один брокер confluentinc/cp-kafka:7.6.0 в режиме KRaft.

Сценарий:

  1. Сохранить и отправить первый заказ, чтобы producer успел подключиться.
  2. Приостановить контейнер Kafka и сохранить три новых заказа с событиями Outbox.
  3. Выполнить три цикла отправки. После каждого должны оставаться три ожидающих события и ноль потраченных попыток.
  4. Возобновить Kafka в блоке finally до остановки producer.
  5. За ограниченное время разобрать очередь и проверить, что все четыре ID событий дошли до Kafka.

Таймаут одной публикации равен двум секундам. В omni-box 0.3.0 этот таймаут и TransientError откладывают публикацию, не расходуя лимит попыток события. Проверка не распространяет это поведение на остальные ошибки публикации. Начатая отправка может дойти после таймаута, поэтому при восстановлении проверяются доставленные ID и готовые строки Outbox, а не строго одна запись Kafka на событие.

Результат запроса BACKLOG_SQL приведён в обеих версиях статьи. Статусы и доставка проверяются через assert; строки PASS сообщают о пройденных проверках. Пауза длится секунды, а не час. Часовой простой в статье посчитан, а не воспроизведён нагрузочным тестом. Стенд с одним брокером не проверяет репликацию, длительную пропускную способность или вместимость БД.

Исходный код практикума на GitHub.