Как обнаруживать и реагировать на проблемы с отменой брони
Что проверяют
Это задача на проектирование надёжного процесса, а не на знание пакета логирования. Интервьюер хочет услышать, что отмена состоит из нескольких шагов с внешними системами и каждый может сломаться отдельно. Следом обычно спрашивают: деньги вернули, а место у поставщика не освободилось, что дальше?
Как отвечать
Начните с модели. Отмена это не флаг IsCanceled, а конечный автомат: cancel_requested, refund_pending, cancelled, cancel_failed. Каждый переход пишется в базу, поэтому застрявшую бронь видно простым запросом.
Обнаружение:
- метрики: через
prometheus/client_golangсчётчикbooking_cancel_totalс меткой результата и гистограмма длительности. Алерт на долю ошибок и рост p99, а не на каждую единичную неудачу; - зависшие статусы: фоновая задача раз в несколько минут ищет брони в промежуточном статусе дольше порога. Так ловится то, чего нет в логах: ошибки не было, был таймаут или падение процесса;
- сверка: периодическое сравнение статусов с платёжным провайдером и поставщиком;
- логи и трассировка:
log/slogс полямиbooking_idиtrace_id, спаны OpenTelemetry через все вызовы.
Реакция:
- повторы: только для временных ошибок, с экспоненциальной задержкой и джиттером, каждый вызов под
context.WithTimeout. Ошибки оборачиваются черезfmt.Errorfс%wи разбираютсяerrors.Is, чтобы отличить «повторить» от «не повторять»; - идемпотентность: ключ идемпотентности у запроса на возврат, иначе повтор вернёт деньги дважды;
- события: transactional outbox, чтобы смена статуса и отправка события не расходились;
- ручной разбор: после исчерпания попыток бронь уходит в очередь поддержки с понятной причиной.
Где спотыкаются
Логируют сам факт отмены и считают это мониторингом. Проблему выдаёт отсутствие события или застрявший статус, а не строка в логе.
Повторяют всё подряд, включая ответ поставщика «бронь не найдена», и забивают очередь запросами, которые никогда не пройдут.
Не думают о компенсации. Если возврат прошёл, а освобождение места упало, нужен шаг, который доводит процесс до конца или откатывает его, иначе данные разъедутся навсегда.