Commit graph

4 commits

Author SHA1 Message Date
a2727a9ac4 chore(stability): harden runtime, observability, and test coverage
Pacote de endurecimento focado em rodar 24/7 no NAS sem surpresas.

DB / persistence
- Register a datetime adapter so Python 3.12+ stops warning about the
  deprecated default; emits "YYYY-MM-DD HH:MM:SS[.ffffff]" to preserve
  existing string-based comparisons in get_enhanced_stats.
- PRAGMA journal_mode=WAL on init (concurrency + crash safety on the
  NAS) and synchronous=NORMAL per connection (cheap, WAL-safe).
- Two composite indexes: (author, subreddit) and (media_type,
  downloaded_at) — speed up the gallery and cleanup queries.

API surface
- New /health router with no auth dep, returns booleans for db /
  ffmpeg / downloads_writable / scheduler plus the package version and
  whether Basic Auth is configured. Reachable even when
  RMC_AUTH_USER/PASS are set, so it can be wired into Container
  Manager / external monitors.
- Refactor: move require_auth() from app-level dependency to per-router
  include_router(..., dependencies=[require_auth()]); /health is the
  only route that opts out.
- Rate limit (60/min per IP+path) on every POST/PUT/DELETE in config:
  subreddits, users, blacklist.*, settings.* — protects config.yaml
  from runaway loops or spam.

Observability
- Replace silent `except Exception` in main and scheduler with
  exc_info=True logging and a new collector_status["last_error"] field
  surfaced via /api/collector/status, so a failed 3am scheduled run
  isn't invisible.
- RotatingFileHandler (10 MB × 5 backups) caps collector.log around
  60 MB on the NAS volume.

Quality
- tests/test_router_scheduler.py covers status / config (interval +
  cron) / history / run-now / collector run / individual collect
  validation. scheduler.py coverage 25% → 55%, total 55% → 58%
  (135 → 151 tests).
- Type extractors.gfycat (cast yt-dlp Any to str), removed from the
  mypy ignore list. First module destravado — pattern for the rest.

Verified locally: ruff + mypy + 151 pytest green; docker container
boots healthy in 6s; PRAGMA journal_mode reports `wal`; 70 POSTs to
/api/subreddits returned 60 OK + 10 HTTP 429.
2026-05-17 18:11:45 +01:00
b4a2f303ac ci: add mypy job + pre-commit hook, tighten type annotations
- .github/workflows/ci.yml: new 'types' job runs mypy src/; docker now needs lint+types+test
- .pre-commit-config.yaml: add mirrors-mypy hook on src/ with types-requests, types-PyYAML
- pyproject.toml: add per-module overrides ignoring legacy modules (main, downloader, reddit_client, database, extractors.{reddit,gfycat}) while keeping src/web/ strict
- src/web/deps.py: type DOWNLOADS_DIR explicitly as Path
- src/web/config_manager.py: type guards on get_subreddits/users/blacklist returns
- src/web/routers/favorites.py: dict[str, object] for result, avoid in-place + on object
- src/web/routers/media.py: dict[str, object] for delete result
- src/web/rate_limit.py: move Awaitable/Callable under TYPE_CHECKING
- ruff format + auto-fix on src/ + tests/
2026-05-17 11:58:40 +01:00
34c2b16e19 test: cover routers, auth, rate limit, config_manager, imgur extractor
- tests/test_auth.py: enable/disable via env, valid/invalid creds
- tests/test_rate_limit.py: bucket math + window expiry
- tests/test_router_media.py: path traversal (file/thumb), paginated subreddits/authors, blacklist preview shape, DELETE flow, cleanup-by-type 400 paths
- tests/test_router_stats.py: cache TTL, .json exclusion, missing dir
- tests/test_router_favorites.py: paginated favorites/authors, no N+1 (query count), favorites_only filter
- tests/test_router_config.py: CRUD subreddits/users/blacklist
- tests/test_config_manager.py: case-insensitive dedupe, blacklist removes from collection, domain normalization
- tests/test_extractors_imgur.py: i.imgur direct, gifv->mp4, albums/galleries -> None

src/database.py: resolve RMC_DB_PATH lazily in Database() so tests can monkeypatch the env per case (no more module-import capture)

Result: 135 passed (was 77). Coverage 55% global; 100% on auth/imgur, 96% rate_limit, 84% stats router, 80% config_manager.
2026-05-17 11:54:40 +01:00
986f1dfef4 chore: checkpoint baseline (routers, tests, pyproject) 2026-05-17 11:40:35 +01:00