Pāriet uz saturu

Backend

Flask REST API. Atsevišķs repo geo-backend. Deploy uz Hetzner Docker.

Tehnoloģijas

  • Python 3.11 + Flask app-factory (create_app geo-backend/app.py)
  • Flasgger — auto-generated Swagger UI no YAML docstrings
  • SQLAlchemyPostgreSQL 16 + PostGIS (native uz host)
  • Flask-Migrate — schema migrations
  • Stripe — subscriptions + webhook
  • JWT auth@auth_required decorator
  • prometheus-client — custom /metrics endpoint
  • Gunicorn 3 workers production

App layout

app.py                          ← create_app() factory
config/settings.py              ← env config (DATABASE_URL, JWT_SECRET, ...)
models/                         ← SQLAlchemy models
  ├── company.py
  ├── user.py
  ├── device.py + device_activity.py
  └── feedback.py
routes/                         ← Blueprints
services/                       ← Biznesa loģika + importeri
middleware/                     ← @auth_required dekorators

Blueprints

5 reģistrēti create_app:

auth_bp (/auth/*)

Endpoint Method Auth Mērķis
/auth/register POST Jauns konts (rate-limit 3/h)
/auth/login POST JWT issue (rate-limit 5/min)
/auth/password-reset POST Parole reset e-pasts
/auth/password-reset/confirm POST Apstipriniet ar token

api_bp (/api/*)

Visi prasa @auth_required (Bearer JWT vai bare token).

Endpoint Method Mērķis
/api/ca/<n> GET CA polygon ar WKT
/api/employees GET, POST, DELETE Komandas pārvalde
/api/subscription/list GET ntfy abonementu saraksts
/api/subscription POST Pievienot kadastram
/api/subscription/<id> DELETE Atcelt
/api/encumbrance/history/<n> GET Apgrūtinājumu vēsture
/api/property/<id>/{mikroliegumi,iadt,biotopi,sugu-atradnes} GET DAP datu paneles
/api/forest/by-cadastre/<n> GET VMD MVR kompartmenti
/api/geocode/{search,reverse} GET VAR adrešu meklēšana

Pilns saraksts: /apidocs Swagger UI.

stripe_bp

Stripe webhook (rate-limit exempt, jo Stripe atkārto līdz pieņemts).

device_bp (/api/device/*)

Endpoint Auth Mērķis
/api/device/register App startup device registration
/api/device/heartbeat Periodisks ping ar metrikām

services_config_bp

/api/services-config — public, mobile lasa, lai atjauninātu services.json config bez APK update.

Auth middleware

middleware/auth_required.py:

  • Validē JWT no Authorization header (Bearer <token> vai bare <token>)
  • Ielādē g.user, g.company
  • Atgriež 403 subscription_expired, ja Stripe sub aptver
  • AUTH_BYPASS=1 vidēs (default ON dev'ā) — endpoint'i strādā ar synthetic test user; uzlikt AUTH_BYPASS=0 prod'ā

Importeri

Standalone Python moduļi services/ ar import_all(db_url) + argparse main().

Daily (katru dienu)

Skripts Datu avots Cron Aptuvenais ilgums
vzd_refresh.py --include-vmd VZD kadastrs + VMD CA polygons 03:00 ~17 min
encumbrance_diff.py Apgrūtinājumu diff + ntfy push 04:00 ~5 min
lad_deadline_notifier.py LAD termiņi → ntfy 06:00 ~10 sek

Weekly (pirmdienās)

Skripts Datu avots Cron Aptuvenais
lad_import.py LAD lauku bloki, ainavu elementi 04:00 ~2 min, 333K rindas
var_import.py VAR adreses (data.gov.lv CKAN) 04:30 ~5 min, 549K punkti
iadt_import.py DAP ĪADT + dabas pieminekļi 05:00 ~2 min, 17K
biotopi_import.py DAP EU biotopi 05:30 ~3 min, 68K
sugu_atradnes_import.py DAP sugu atradnes 05:45 ~3 min, 275K
lvm_infra_import.py LVM ceļi/tilti/drenāža 06:00 ~1 min, 277K
lvgmc_water_import.py LVĢMC upes, ezeri 06:30 ~30 sek, 471
osm_heritage_import.py OSM kultūras pieminekļi 07:00 ~1 min, 2.6K
mikroliegumi_import.py DAP mikroliegumi SHP 07:30 ~1 min, 4.7K

ArcGIS REST koplietotā loģika

iadt, biotopi, sugu_atradnes importeri koplieto services/_importer_common.py:

  • fetch_arcgis_page / iterate_arcgis_layer — pagination
  • to_multipolygon_wkt — GeoJSON → WKT ar point buffer
  • epoch_ms_to_date, int_or_none, update_import_meta — common helpers

Pievienojot jaunu ArcGIS REST importeri (LĢIA, NKMP utt.), atkārtoti izmantot šo moduli — paraugi ir 3 esošie importeri (~150 LOC katrs).

Domēna servisi

Ne-importeri, bet biznesa loģika:

Serviss Mērķis
vmd_api.py VMD public API klients (CA WKT fetch)
encumbrance_diff.py Apgrūtinājumu salīdzinājuma loģika + ntfy push
stripe_service.py Stripe checkout + sub status helpers
email_service.py Gmail SMTP integrācija notifikācijām un kļūdām
lad_deadline_notifier.py LAD termiņa notifikāciju ģenerēšana
vzd_local_service.py Atsevišķa Flask app uz port 5050 ar VZD/VMD lookups + /api/geocode/* + custom Prometheus exporter

Konteinera arhitektūra

Divi konteineri no tā paša Docker image (registry.gitlab.com/.../geo-backend:latest):

Konteiners Port Skripts Mērķis
geo-backend 5000 gunicorn app:app Auth, Stripe, devices
klm-vzd-service 5050 python services/vzd_local_service.py VZD lookups + geocode + Prometheus /metrics

Postgres ir native uz host (port 5432), nav Docker'ī. DATABASE_URL no abiem konteineriem norāda uz host.docker.internal:5432. Razons: pg_dump/backup vienkārši, dati ārpus Docker volumes.

Custom Prometheus metrikas

klm-vzd-service publicē uz /metrics. Lasāmais resursu saraksts (klm_* prefiks):

  • klm_api_requests_total{endpoint} — counter
  • klm_cron_last_run_seconds{cron_job} — Unix timestamp pēdējam cron run
  • klm_cron_last_exit_code{cron_job} — pēdējais exit code (0 = OK)
  • klm_data_freshness_seconds{resource} — sekundes kopš pēdējā import_meta atjauninājuma
  • klm_db_row_count{table} — DB rindu skaits galvenajām tabulām
  • klm_device_subscription_count — Stripe aktīvas subs
  • klm_import_rows_total{resource} — pēdējā import rindu skaits
  • klm_unique_device_count — unikāli device_token no user_subscription tabulas
  • klm_notifications_sent_24h{delivered} — ntfy push notifikācijas 24h ar success/fail labels

Deploy

Push uz main → GitLab CI:

  1. build — Docker image (~3 min)
  2. init-dbdeployment/postgres-init/*.sql (tikai kad mainās)
  3. deploy — SSH uz Hetzner: pull image, recreate geo-backend + klm-vzd-service konteinerus, install crontab, 3 min health check

Pilna deploy plāns + cron pattern: geo-backend/docs/DEPLOYMENT.md.

Diska budžets uz Hetzner

Komponents Aptuvenais izmērs
/var/lib/postgresql 16 GB (15 GB vmd_db + indeksi)
/var/lib/docker (overlay + images) 5-10 GB pēc prune
/var/backups/klm-postgres ~5 GB (3 weekly backups @ 1.3 GB)
Observability volumes ~2.5 GB (Prometheus TSDB)
Wiki + nginx logs < 100 MB

Pilns 38 GB diska budžets, parasti 60-75% lietots pēc tīrīšanas.

Backup un Disaster Recovery

  • PG backup: svētdienās 03:00 (/opt/klm/backup_db.sh)
  • Cleanup: ik dienas 02:00, tur 21 dienu vai dzēš 0-baitu failus
  • Plāns: docs/DISASTER_RECOVERY.md

Saites uz dziļāku saturu