У нас есть автопочинка объявлений: получаем статус, исправляем текст или фото, пересобираем XML-фид и ждём следующей загрузки. На бумаге цикл замкнут. На практике два объявления из Серпухова и Солнечногорска провисели так почти два месяца.
Оба сначала получили rejected, затем перешли в blocked. Исправленный контент в базе был, а в кабинете объявления не возвращались. Мы заметили это не по алерту, а когда вручную сверили три множества:
IDs в нашей БД ∩ IDs в текущем XML-фиде ∩ IDs, которые возвращает API кабинета
Разность оказалась маленькой — две записи, — поэтому обычные метрики выглядели здоровыми. Счётчик «исправлено» рос: пайплайн действительно менял данные. Но он измерял завершение внутреннего шага, а не возврат объявления в публикационный контур.
Ошибка была в модели состояний. Мы считали rejected и blocked вариантами одной проблемы:
if status in {Status.REJECTED, Status.BLOCKED}: fix_content(ad) mark_fixed(ad)
Для rejected этого хватало, пока объявление оставалось участником загрузки. Для двух наблюдавшихся blocked — нет: к моменту исправления их ID уже отсутствовали в актуальном фиде. Получался честный, но бесполезный mark_fixed().
Исправление получилось не в промпте и не в наборе запрещённых слов. Мы разделили «контент исправлен» и «объект снова попал в контур»:
fix_content(ad) if ad.status == Status.BLOCKED and ad.requeue_attempts == 0: include_in_next_feed(ad) request_autoload() ad.requeue_attempts = 1 verify_visible_in_account(ad.id)
Повтор ограничили одним. Иначе системная блокировка могла превратить починку в бесконечный цикл «добавили → отклонили → добавили». После одной неудачной попытки объект уходит человеку с исходным статусом и причиной из отчёта загрузки.
Что не сработало:
повторная генерация текста сама по себе — исправляла запись, но не возвращала ID в фид;
метрика по числу выполненных фиксов — показывала активность, а не результат;
сравнение только БД и кабинета — не объясняло, на каком участке исчез объект;
безлимитный retry — выглядел простым решением, но скрывал бы постоянные блокировки и дёргал модерацию.
После разового возврата в фид оба объявления снова появились в работе 30 июля. Замер здесь скромный, но однозначный: было 0 из 2 восстановленных, стало 2 из 2. Важнее другое: теперь успех считается только после проверки внешнего состояния, а не после локального UPDATE.
Пока полная сверка не автоматизирована, раз в неделю строим разность трёх множеств. Такой контроль оказался полезнее ещё одного «успешного» счётчика.
А где у вас проходит граница успеха: на записи в собственной БД или на подтверждённом состоянии внешней системы?Программированиеавтоматизацияинтеграции