Files

3.4 KiB
Raw Permalink Blame History

Proposal: crawler-queue

Why

Сейчас фазы сбора и обработки не разделены: каждый краулер (telegram/rss) сам собирает посты и сам же (через classifier.classify) разбирает их на классификацию. Это последовательно: весь прогон — один поток, один источник за раз. При этом самая дорогая часть — фаза 3 (классификация через Ollama, дотягивание текста трафилатурой) — выполняется последовательно и без видимости процесса: непонятно, сколько кандидатов в очереди, какие источники живы, что упало.

Пользователь хочет:

  1. Отдельная страница /crawlers — статус работы краулеров (alive/dead, last_fetch, ошибки) и размер очереди.
  2. Двухфазный сбор: (1) краулеры проходят по источникам → ищут новых кандидатов; (2) найденное кладётся в очередь; (3) воркеры разбирают очередь в НЕСКОЛЬКО ПОТОКОВ.

Анализ текущего кода:

  • Очередь фазы 2 уже существует — это posts со status='new' и classified IS NULL OR classified=0 (классификатор выбирает именно их, SELECT ... WHERE classified IS NULL OR classified=0 LIMIT ?).
  • Отдельная таблица crawl_queue НЕ нужна — она дублировала бы posts. «Размер очереди» = COUNT(*) FROM posts WHERE classified IS NULL OR classified=0.
  • Чего нет: (а) параллельной фазы 3 (ThreadPoolExecutor), (б) страницы /crawlers, (в) разделения «сбор» и «обработка» как независимых запусков.

Goal

  • Параллельная фаза 3: воркеры (N потоков) разбирают очередь posts(classified=0) — классификация (keywords → Ollama) + дотягивание текста (trafilatura) по пайплайну classifier.classify.
  • Страница /crawlers (веб, за auth): таблица источников (slug, name, crawler, status, last_fetch, last_error, error_count, priority), размер очереди (pending/processing/done), кнопки «Запустить сейчас» и «Сбросить dead».
  • Разделение: crawler/worker.py (фаза 3, N потоков) и crawler/crawl_sources.py (фаза 1: собрать новых кандидатов в очередь) — независимые запуски.
  • Терминология (для доков): true-конкурентность на IO-bound задачах через потоки; GIL не мешает, т.к. фаза 3 — ожидание сети.

Non-goals

  • Не вводим Redis/RabbitMQ/брокеры — SQLite-очередь (claim по posts) достаточна.
  • Не выносим в микросервисы — всё в рамках существующего веба/краулера.
  • Не переписываем telegram_crawler; RSS-краулер уже работает.