Задача
На бирже отклик номер два читают, а номер сорок — нет. Ценность не в том, чтобы видеть заказы, а в том, чтобы видеть их первым и понимать, стоит ли вообще тратить отклик. Нужен был инструмент, который сам смотрит ленты, отбирает подходящее и присылает в Telegram вместе с решающей цифрой — сколько человек уже откликнулось.
Три предположения, которые замер опроверг
Что официальная лента полна. Первая версия читала RSS — очевидное решение. Сличение со страницей раздела показало, что из 30 карточек первой страницы 16 в ленте отсутствуют: все вакансии и закреплённые объявления. Проверка через фильтр по типу подтвердила диагноз, а двенадцать минут наблюдения подряд исключили версию про задержку — пропавшие записи не появляются позже.
Что лента отдаёт заголовки кэширования. Не отдаёт ни ETag, ни Last-Modified, и генерируется заново на каждое обращение. Код, который ждал ответа 304, был мёртвым и удалён.
Что сжатие не применяется. Применяется: страница едет 39 КБ вместо 393. Это изменило расчёт нагрузки — частый опрос оказался посилен, а не расточителен.
Каждое предположение выглядело безобидным, и каждое меняло архитектуру. Проверка стоила минут, цена ошибки — половина потока заказов.
Что достали из разметки
Разбор карточки даёт тип публикации, возраст, просмотры и число откликов. Последнее видно без входа на сайт, хотя на странице самого заказа блок со статистикой от гостя скрыт. Это и есть цифра, ради которой всё затевалось: заказ с сорока откликами уже разобран.
Отбор
Стоп-слова проверяются только по заголовку и категории: фраза «потом ещё логотип понадобится» в теле заказа не должна убивать подходящую задачу — на живой ленте это ловилось. Но одного заголовка мало: вакансия «IT-специалист на Java» прошла отбор по слову «парсинге», а в тексте оказалось вербовочное объявление. Понадобился отдельный список стоп-фраз по тексту.
Перенос на сервер без Node
Порт на PHP написан на синтаксисе 5.3 — array() вместо коротких массивов, никаких стрелочных функций: скучный код, который запускается везде, лучше красивого, который упадёт на старой системе. Формат настроек и состояния сохранён, переезд сводится к копированию двух файлов.
Совпадение проверено сличением, а не на глаз: обе версии на одной ленте из 55 позиций отобрали одни и те же 11 заказов.
Отдельно написан разведчик окружения на синтаксисе PHP 5.2 — чтобы запуститься там, где остальное откажется, и внятно сказать почему. Он ловит два отказа, ради которых и нужен: OpenSSL старше 1.0.1 не умеет TLS 1.2, а устаревший набор корневых сертификатов рвёт соединение. Проверку сертификатов код при этом не отключает: инструмент приносит данные для решений, и подменить их не должен никто.
Что нашлось в собственном коде
Счётчик отправленных сообщений рос независимо от ответа Telegram: заказ помечался просмотренным, в логе значилась доставка, а сообщение могло не уйти — и больше бы не ушло. Рядом обнаружилось отсутствие таймаута: зависший запрос занял бы запуск, а планировщик молча пропускал бы каждый следующий до предела в 72 часа.
Результат
Охват ленты вырос с 14 карточек из 30 до 30 из 30 плюс вторая площадка. Трафик за проход — 39 КБ вместо 393. Задержка до уведомления — две с половиной минуты вместо ручного просмотра. Требования к серверу — только PHP и cURL.
Срок: четыре дня, семь коммитов. Собственный проект.