61be447b41
Самая тяжёлая находка смены, вылезла из вопроса владельца «показано 0, почему? там один же есть» — из сверки карточки с кабинетом глазами. Замер на боевом: запрос портала к Директу отвергается с кодом 400 — «В params отсутствует обязательное поле IncludeVAT». А код ответ не проверял: брал тело, переводил в число и получал ноль. То есть «показов не было» — не факт, а проглоченная ошибка. Чем накрывается. Это единственный источник числа показов, и у него две работы: число «Показано» на карточке и основание списать деньги за открученную рекламу. Значит ни за один показ клиенту не выставлялся счёт — реклама шла за наш счёт. И тихий ноль опасен сам по себе: затирает настоящее число на карточке, а при истёкшем сроке закрывает кампанию с возвратом всей заморозки. Почему не поймали раньше: ноль выглядит как «показов ещё не было» — законное состояние новой кампании. Отличить «не было» от «не смогли спросить» портал не умел. На этом месте с самого начала висел TODO про сверку формата перед боем. Три правила и три сторожа: - IncludeVAT в запросе — без него Директ отвергает запрос целиком; - processingMode auto — иначе отчёт строится в фоне и приходит пустое тело; - громкая ошибка вместо тихого нуля при не-2xx и нечисловом ответе. Наверху ошибка уже обработана правильно: обход пишет предупреждение и идёт дальше, а «Пауза» при такой ошибке не отпускает деньги. Четвёртая мина, вскрытая сторожем уникальности: имя отчёта строилось из секунд, два вызова в одну секунду получали одно имя и второй читал кэш первого. Добавлен случайный хвост. Настоящий ноль из Яндекса остаётся нулём — отдельный сторож держит и это. Прогон: 393 сторожа блока рекламы, статанализ 0, стиль чист. Схема не менялась. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>