list_bans() was calling geo_service.lookup() once per IP on the page (e.g. 100 sequential HTTP requests), hitting the ip-api.com free-tier single-IP limit of 45 req/min. IPs beyond the ~45th were added to the in-process negative cache (5 min TTL) and showed as no country until the TTL expired. The map endpoint never had this problem because it used lookup_batch (100 IPs per POST). Add http_session and app_db params to list_bans(). When http_session is provided (production path), the entire page is resolved in one lookup_batch() call instead of N individual ones. The legacy geo_enricher callback is kept for test compatibility. Update the dashboard router to use the batch path directly. Adds 3 tests covering the batch geo path, failure resilience, and http_session priority over geo_enricher.
28 lines
1.5 KiB
Markdown
28 lines
1.5 KiB
Markdown
# BanGUI — Task List
|
|
|
|
This document breaks the entire BanGUI project into development stages, ordered so that each stage builds on the previous one. Every task is described in prose with enough detail for a developer to begin work. References point to the relevant documentation.
|
|
|
|
---
|
|
|
|
## Completed
|
|
|
|
### [DONE] Fix: Country column shows "—" for blocklist-import IPs in ban list
|
|
|
|
**Root cause:** `ban_service.list_bans()` resolved geo data one IP at a time via
|
|
`geo_service.lookup()`, which uses the ip-api.com single-IP endpoint (45 req/min
|
|
free tier limit). A page of 100 bans triggered 100 sequential HTTP requests;
|
|
after the ~45th request ip-api.com applied rate limiting, all remaining IPs were
|
|
added to the in-process negative cache (5 min TTL), and they showed "—" in the
|
|
country column permanently until the TTL expired. Because the map endpoint
|
|
(`bans_by_country`) used `lookup_batch` (100 IPs per POST), it never hit the
|
|
rate limit, which is why the map showed colours while the list did not.
|
|
|
|
**Fix:** Added `http_session` and `app_db` parameters to `list_bans()`. When
|
|
`http_session` is provided (production path via the dashboard router), the entire
|
|
page of IPs is resolved in a single `geo_service.lookup_batch()` call instead of
|
|
100 individual ones. The legacy `geo_enricher` callback is kept for backwards
|
|
compatibility in tests. Updated `dashboard.py` to pass `http_session` and `db`
|
|
instead of constructing a per-IP enricher closure. Added 3 new tests covering
|
|
the batch path, failure resilience, and priority over `geo_enricher`.
|
|
|