Мой чат-бот молчал 17 дней. Все наши проверки при этом говорили, что всё работает

У нас есть сервис, который отвечает за продавцов в чатах на Авито: покупатель пишет — ИИ-менеджер читает и отвечает, не дожидаясь человека. Работает это через вебхук: Авито стучится к нам каждый раз, когда в чате появляется новое сообщение. Стучится — и мы обрабатываем.
У нас есть сервис, который отвечает за продавцов в чатах на Авито: покупатель пишет — ИИ-менеджер читает и отвечает, не дожидаясь человека. Работает это через вебхук: Авито стучится к нам каждый раз, когда в чате появляется новое сообщение. Стучится — и мы обрабатываем.

Так вот, у одного клиента вебхук молчал с 28 августа. Три недели. А наш собственный сторож всё это время писал в лог, что всё в порядке.

Первая версия: подписка слетела

У нас есть автоматическая проверка: раз в час она смотрит список активных вебхук-подписок и сверяет с тем, что должно быть у каждого клиента. Когда по конкретному аккаунту долго нет входящих сообщений, первая мысль всегда одна — «подписка отвалилась, надо переподписать».

Мы полезли разбираться и нашли кое-что похуже: у шести аккаунтов из одиннадцати активных подписки не было вообще никогда. Не «слетела» — просто ни разу не создавалась. Автоматическая подписка у нас стояла только в одном месте: когда клиент открывал свой кабинет и его мессенджер отвечал «ок». Если клиент кабинет не открывал, а просто работал через бота, подписка так и оставалась пустой строкой в базе. А наша же проверка эту пустую строку читала как «отписался», а не как «никогда не был подписан», — и чинить её не пыталась, потому что логика была написана под другой сценарий.

Починили: добавили отдельный проход крона именно для «никогда не подписывался». Обрадовались, что нашли причину тишины.

Тот самый аккаунт всё равно молчал

А у конкретного клиента, из-за которого всё это началось, подписка как раз БЫЛА. Причём настоящая: тот же адрес, тот же секрет, всё сходится. Наша проверка после фикса должна была написать «всё ок» — и написала.

Дальше стало интереснее. Мы решили перепроверить список подписок Авито вручную, тем же способом, каким это делает наш сторож. И получили «подписок нет». Пустой список. При том что за пять минут до этого мы своими глазами видели в базе рабочий адрес и совпадающий секрет.

Ошибка нашлась не в коде, а в том, каким ключом мы спрашивали. Список подписок в API Авито привязан не к аккаунту клиента, а к тому, чем ты стучишься: если спросить личным API-ключом — ты получаешь список приложения, и он пустой. Если спросить OAuth-токеном конкретного клиента — список честный, и наш адрес там есть. Одна и та же реальность даёт два противоположных ответа в зависимости от того, с какой стороны её спросить. И наш сторож, как назло, часть проверок делал не тем ключом.

То есть три недели мы гоняли по кругу симптом, который сам себе противоречил: одна проверка говорит «подписки нет, переподпишись», другая — «подписка есть, всё в порядке». Обе выполнялись на одном и том же коде, просто разными путями с разными кредами. Это заняло больше времени, чем должно было, потому что мы верили каждой проверке по очереди, а не спросили сразу — а судим ли мы вообще об одном и том же.

Мы всё равно не знаем, помогло ли

Сегодня утром я сделал единственное, что оставалось: отправил Авито тот же адрес с тем же секретом ещё раз, поверх уже существующей подписки. Это не должно было ничего изменить — с точки зрения данных подписка и так была правильной. Но иногда помогает именно это: не исправление конфигурации, а сам факт нового рукопожатия, будто сервер Авито должен заново «увидеть» адрес, чтобы начать в него стучаться.

Отправил. Получил 200. И сейчас, пока пишу этот текст, входящих сообщений от этого клиента всё ещё не было. Последнее живое сообщение в самом Авито — от вчерашнего вечера. Значит, покупатели клиенту пишут, а до нас это не долетает до сих пор, либо просто ещё не успело.

Честно: я не знаю, почему Авито перестал стучаться в правильный адрес с правильным секретом на три недели, и не знаю, почему повторная подписка должна это исправить, если по всем формальным признакам старая была рабочей. У меня есть рабочая гипотеза и есть план проверить её через сутки — не более того.

Что я для себя вынес: когда монитор говорит «всё зелёное», первый вопрос — не «точно ли зелёное», а «а той ли рукой мы вообще щупаем». Два разных ответа на один вопрос — это не повод верить более удобному, это повод остановиться и спросить, откуда взялось расхождение. У нас оно взялось из мелочи — какого именно клиента API считает владельцем запроса, — а стоило три недели тишины у живого клиента, который эти три недели не знал, что его чат-бот ничего не читает.