Files
vesti/openspec/changes/archive/2026-09-16-crawler-queue/tasks.md
T

40 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: crawler-queue
## 1. Воркер (фаза 3)
- [x] 1.1 crawler/worker.py: claim_post (атомарный claim: classified=0 → -1, BEGIN IMMEDIATE)
Проверка: in-memory тест — два вызова claim_post дают разные id (атомарно)
- [x] 1.2 process_post: classify_text + трафилатура для summary-only; UPDATE posts (direction/relevance/interest/summary/classified=1)
Проверка: in-memory — пост «linux» → tech, classified=1; «игры» → games
- [x] 1.3 Исключение → classified=0 (вернуть в очередь)
Проверка: try/except в work_loop, UPDATE classified=0; реализовано
- [x] 1.4 run(workers=8, limit=200): ThreadPoolExecutor, as_completed, счётчики (processed/classified/llm_ok)
Проверка: `python -m crawler.worker --workers 4 --limit 2` → 8 обработано; без ошибок
## 2. Сбор (фаза 1)
- [x] 2.1 crawler/crawl_sources.py: запуск telegram_crawler + rss_crawler (сбор новых кандидатов в очередь)
Проверка: `python -m crawler.crawl_sources --all` → запускает оба; `--crawler rss` — только RSS
## 3. Страница /crawlers
- [x] 3.1 web/app.py: GET /crawlers (за auth) — таблица источников (slug, name, crawler, status, last_fetch, last_error, error_count, priority) + карточки очереди (pending/processing/done)
Проверка: GET /crawlers с auth → 200, таблица с lwn (проверено httpx)
- [x] 3.2 web/templates/crawlers.html — шаблон (таблица + карточки + кнопки)
- [x] 3.3 POST /crawlers/run → запуск worker.run (фаза 3); POST /crawlers/reset → sources.status='alive', error_count=0
Проверка: POST /crawlers/run → воркер реально стартует (logs/worker.log), 200/302; reset — UPDATE
## 4. Интеграция и доки
- [x] 4.1 AGENT.MD — команды worker/crawl_sources (добавлены)
- [x] 4.2 STATUS.md / TODO.md — страница /crawlers, параллельная фаза 3 (обновлены)
- [x] 4.3 `openspec validate crawler-queue` → 0 ошибок
- [x] 4.4 TODO.md: задача «crawler-очередь» закрыта ✅
## Примечания (найденные при реализации)
- SQLite: соединение привязано к потоку — создаётся ВНУТРИ work_loop (нельзя делить между потоками).
- Локальная Ollama (qwen3:8b) держит 1 слот — 8 параллельных LLM-запросов → таймауты (посты возвращаются в очередь, не теряются). Добавлен `LLM_SEM` (threading.BoundedSemaphore, MAX_CONCURRENT_LLM=2).
- Очередь = posts (classified IS NULL OR 0) — отдельная таблица НЕ нужна (дублирование).
- error_count/etag для RSS — из rss_state (в sources их нет); запрос /crawlers использует COALESCE.
- **SOURCE_RULES (classifier/keywords.py)**: правило источника с приоритетом над словарём и LLM. `lwn → tech` — все посты LWN (технологическое СМИ) получают направление tech детерминированно, без LLM (method='source-rule'). Работает в worker.py и старом CLI classifier.classify (оба JOIN sources → source_slug).