Files
Deal/.superpowers/sdd/channel-discovery/task-2-report.md
T
Rustam Khalimov 27c7831910
ci / build-test (push) Canceled after 0s
Deal — единая кодовая база
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 зелёные.
2026-09-11 23:56:47 +03:00

85 lines
5.4 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.
# Task 2 — Отчёт: BanGuard (квоты, паузы, flood)
Статус: **DONE**
## Что сделано по шагам
### Step 1: Модуль `backend/app/services/ban_guard.py` (создан)
Реализован по интерфейс-спеке брифа (в брифе «дословного» кода нет — только сигнатуры
и поведение, см. Concerns #1):
- `joins_today_auto() -> int``count(*)` из `disc_log` по `event='join_auto'`
с `created_at >= начало текущих UTC-суток` (`datetime.now(timezone.utc)
.replace(hour=0,minute=0,second=0,microsecond=0)` → ms).
- `can_auto_join() -> bool``joins_today_auto() < discJoinLimit` И `not flood_today()`
И `not global_paused()`.
- `async wait_join_delay() -> None` — `asyncio.sleep(random.uniform(discJoinDelayMin,
discJoinDelayMax))` (значения из `store.get_setting`).
- `note_flood() -> None` — `store.set_setting("discFloodDay", <start_of_day_ms>)`.
- `flood_today() -> bool` — `discFloodDay == start_of_day_ms` (вчерашний флуд-день
автоматически «протухает» в полночь UTC).
- `global_paused() -> bool` / `set_global_pause(v: bool) -> None` — setting `discPaused`.
- `search_pause() -> float` — `random.uniform(2.0, 4.0)`.
Детали реализации:
- Хелпер `_start_of_day_ms()` общий для квоты, флуда и паузы.
- Ключи настроек вынесены в модульные константы (`_KEY_*`) — в коде нет «голых» строк.
- `discPaused`/`discFloodDay` не в `DEFAULT_SETTINGS` (рантайм-настройки): `get_setting`
возвращает `None`, который трактуется как «не взведено» (`False`/`0`).
- Стиль модуля — как в соседних сервисах: `from ..db import store`, русские докстринги,
`from __future__ import annotations`.
### Step 2: Проверка на временной БД в контейнере
Первая попытка упала: `ImportError: cannot import name 'ban_guard'` — код копируется в
образ при сборке (`backend/Dockerfile`: `COPY backend/app ./app`), исходники не
монтируются, а образ был собран до создания файла. Выполнена пересборка
`docker compose build app` (2.6s, слой кода — единственный не из кэша), затем команда
из брифа прошла (вывод ниже).
## Изменённые файлы
- `backend/app/services/ban_guard.py` (создан)
## Вывод проверок
### 1. `py_compile`
```
$ cd /c/telbase && python -m py_compile backend/app/services/ban_guard.py
COMPILE_OK # без ошибок
```
### 2. Временная БД в контейнере (команда из брифа Step 2)
```
$ docker compose build app # необходимо, т.к. код запекается в образ
$ docker compose run --rm --no-deps -e PYTHONPATH=/srv -e LEADRADAR_DATA=/tmp/lr_bg --entrypoint python app -c "
from app.db import store; store.init()
from app.services import ban_guard as bg
assert bg.can_auto_join() is True
assert bg.joins_today_auto() == 0
bg.note_flood(); assert bg.flood_today() is True
bg.set_global_pause(True); assert bg.can_auto_join() is False
print('BANGUARD OK')
"
BANGUARD OK
```
Все 4 assert'а из брифа прошли. ✔
### Дополнительно
- Статическая проверка (diagnostics Zed): ошибок и предупреждений нет.
## Concerns
1. **«Весь код — в брифе» — фактически неверно**: в `task-2-brief.md` (и в плане)
нет ни одного блока кода модуля, только интерфейс-спека (~10 сигнатур с описанием
поведения) и команда проверки. «Транскрибировать дословно» было нечего; модуль
реализован по спеке. Очевидных ошибок/противоречий в спеке не нашёл — править было
нечего. Если планировался эталонный код — его нужно добавить в бриф.
2. `wait_join_delay()` и `search_pause()` не покрыты проверкой Step 2 (оба — случайные
паузы; дефолт паузы вступления 50–70 сек, поэтому в проверку они не входили).
Логика тривиальная (`random.uniform` + `asyncio.sleep`), но «живого» прогона нет.
3. `can_auto_join()` при `discJoinLimit <= 0` всегда `False` (осторожная сторона:
лимит 0 = «не вступать»).
4. Клампы пауз (5..600) независимы — `min > max` теоретически возможно через UI
(унаследованный concern из Task 1; в `wait_join_delay` тогда диапазон
«вывернется», но не упадёт). Перекрёстную проверку бриф не требовал.
5. Для проверок последующих задач нужна пересборка образа после каждого изменения
backend-кода (образ не монтирует исходники).