Persist station CRUD across restarts via JSON config

Station CRUD via the API previously mutated the scraper's in-memory
station_mapping only, so changes were lost on restart (and the systemd
service auto-restarts).

- Extract the 130-line hardcoded station_mapping into bundled defaults at
  src/data/stations.json; the scraper loads from a runtime-writable config
  file (STATION_CONFIG_PATH, default stations.json) and falls back to the
  bundled defaults to seed it.
- Add scraper.save_stations() with an atomic temp-file + os.replace write.
- create/update/delete station endpoints now persist and roll back the
  in-memory change if the write fails; re-raise HTTPException so persistence
  errors surface as real 500s instead of being swallowed.
- Backend-agnostic (works for the VictoriaMetrics deployment, which has no
  relational stations table). Runtime stations.json is gitignored.

Also clears pre-existing flake8 debt in water_scraper_v3.py (unused imports,
long lines, duplicate logging import) and dedupes the User-Agent to
Config.USER_AGENT.
This commit is contained in:
2026-07-22 12:51:29 +07:00
parent 6e78225d00
commit 4bc3d82773
5 changed files with 362 additions and 261 deletions
+6
View File
@@ -88,6 +88,12 @@ class Config:
MAX_RETRIES = int(os.getenv("MAX_RETRIES", "3"))
RETRY_DELAY_SECONDS = int(os.getenv("RETRY_DELAY_SECONDS", "60"))
# Station configuration
# Runtime-writable JSON file that persists the station mapping across restarts
# (station CRUD via the API writes here). If it does not exist, the bundled
# defaults in src/data/stations.json are used to seed it.
STATION_CONFIG_PATH = os.getenv("STATION_CONFIG_PATH", "stations.json")
# Web API / CORS settings
# Comma-separated list of allowed origins. Defaults to none (same-origin only);
# set CORS_ALLOW_ORIGINS to a specific list of front-end origins in production.