Ускорение шага 1: CategoryScraper грузит страницы категории 2ГИС не по одной, а пачками поперёк рубрик
через BatchPageFetcher. На остывшем xfetch 2ГИС упал с ~23 мин до ~5 мин и собрал 139 фирм вместо 12.
Общий лимит одновременных xfetch снижен 4→3 (безопаснее под оконный rate-limit сервиса).
Таймауты ИИ/EXA подняты с запасом (латентность моделей плавает, сбор асинхронный, клиент ждёт):
sonar 120→300с, отсев агрегаторов 90→240с, общий AITUNNEL 30→120с, EXA 30→90с. Джоба: один прогон
без авто-ретраев (tries 3→1, чтобы таймаут не перезапускал платный движок трижды) и общий таймаут 900→1800с.
Фиксы, найденные на живом прогоне:
- Письмо «готово» больше не роняет прогон при недоступной почте (тесты на сбой SMTP при status done/empty).
- Яндекс-загрузчик берёт путь к node из config (autopodbor.node_bin, дефолт node) — из-под PHP node
теперь находится; на живом прогоне Яндекс дал 78 фирм вместо 0.
По TDD. Бэкенд автоподбора 262/262, Pint чисто. Живой прогон end-to-end: ~8 мин, 14 новых конкурентов,
списание 300 ₽ корректно.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RunAutopodborSearchJob по завершении (done/empty) шлёт AutopodborReadyMail на contact_email тенанта
(с числом найденных + ссылкой на портал). Письмо не роняет подбор при недоступной почте (try/catch).
Клиент ставит задачу, работает дальше, получает «готово» письмом.
Тесты: SearchJob 4/4 (вкл. Mail::assertSent); Автоподбор unit+feature 183/183; Pint чисто.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>