ci / build-test (push) Canceled after 0s
SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/ Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue, контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер), Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог). Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0, тесты 1340/130/52/38/9 зелёные.
5.6 KiB
5.6 KiB
Discovery — scoped-ревью фикс-волны: вердикт и доработки
Вердикт ревьюера: Ready — With fixes (все 8 заявленных фиксов I1–I4/M1–M5/m1–m6 подтверждены код-ревью; 2 Important + 4 Minor). Смоук-прогон новых веток после правок — зелёный (A–E), образ пересобран, контейнер поднят, API 200.
Findings ревьюера и что сделано
Important
- Search-flood retry storm (
discovery_worker.py) — приFloodWaitErrorключ не двигался, а тик каждые 5 с снова дёргалdiscovery_searchвесь день (флуд > 60 с Telethon не гасит сам), спамя лог flood и блокируя eval/join всех задач. → Исправлено:tick()теперь приban_guard.flood_today()возвращает none (полный стоп discovery-сетевых действий до конца суток — согласуется с «стоп до конца суток» из note_flood); generic-ошибка ключа — после 3 попыток подряд ключ пропускается (advance_search+ лог «ключ пропущен»), счётчик ошибок сбрасывается при успешном поиске. - Re-check после wait_join_delay без BanGuard (
_join_step) — за паузу 50–70 с пользователь мог нажать стоп-кран / случиться флуд, а pending-join всё равно выполнялся. → Исправлено: в условие после паузы добавленоnot ban_guard.can_auto_join()(покрывает стоп-кран, flood дня и суточный лимит).
Minor
- Single-key PATCH ломает инвариант min ≤ max пауз —
PATCH {discJoinDelayMax: 5}при сохранённом min=600 давал инверсию →random.uniformпадал на каждом join-тике. → Исправлено в двух местах:settings_routes.patch_settingsклампит одиночный конец интервала относительно сохранённого другого;ban_guard.wait_join_delayзащитно меняет концы местами (и выходит без паузы, если обе настройки 0). - UPDATE join_failures / delete на 3-й неудаче без ре-валидации status='review' — узкая гонка: человека отклонил кандидата между re-read и падением join.
→ Исправлено: перед инкрементом счётчика статус перечитывается (
row_now); UPDATE идёт сAND status='review'; при выходе из review воркер выходит молча, не трогая запись. - Ручной join в API ждал inline-backfill ~15–30 с (
backfill_dialogспит 1.5–3 с/сообщение) — кнопка «Вступить» висела, прокси с коротким таймаутом показал бы ложную ошибку. → Исправлено:POST /candidates/{id}/joinзапускает backfill в фоне через_spawn(_backfill_quiet(...))(паттерн set_monitor_all), ответ API быстрый, ошибки backfill не роняют запрос. - Skip-лог на каждого человека в поиске — известный minor из отчёта фиксера (concern #2). Оставлен как есть: по одному логу на источник информативно для истории задачи; при желании можно агрегировать («пропущено личных чатов: N») — не критично.
Smoke новых веток (временный скрипт в data/, удалён после прогона)
A_FLOOD_GATE_OK # flood_today -> tick none, search не вызван
B_PAUSE_DURING_DELAY_OK # стоп-кран во сне -> join не выполнен, кандидат review
C_JOIN_FAILURES_REVIEW_GONE_OK # кандидат rejected во время падения join: счётчик 0, запись жива
D_INVERTED_DELAYS_OK # min>max: wait_join_delay не падает (swap)
E_SEARCH_KEY_SKIP_OK # 3 ошибки ключа -> ключ пропущен, searchDone, лог «ключ пропущен»
LR_REVIEW_FIX_SMOKE_OK
Проверки
python -m py_compileизменённых файлов (discovery_worker.py, ban_guard.py, discovery_routes.py, settings_routes.py) — OK.docker compose build app— Built (внутри образа повторныйvite build— ok).docker compose up -d app— контейнер Recreated/Started.GET /api/health— 200{"ok":true,...}; login admin — 200;/api/settingsотдаёт disc-ключи иdiscPaused: false;/api/discovery/tasksи/blacklist— 200{"items":[]}.
Осталось
- Живой E2E с Telegram-аккаунтом (шаги в task-10-report.md §«Осталось для ручной проверки») — вместе с пользователем: поиск → кандидаты → вступить/отклонить → авто-вступление с паузами и расходом лимита. Реальные flood/форумы офлайн не воспроизводятся.