Tuiles visibles en direct après régénération et déploiement webapp distante

- URLs images versionnées (?v=mtime) : une tuile recalculée change d'URL et
  force le rechargement navigateur (cache heuristique contourné), y compris
  en plein run via /api/tiles ; veille permanente 15 s sur la carte
- simulation locale du mode deux machines (docker-compose.local-2m.yml) :
  worker GPU :8974 + webapp légère :8973 au cache séparé output-webapp/
- override webapp pour le Pi 5 (192.168.3.3) : volume /srv/lidar/output,
  rsync vers le worker, labels Traefik (proxy/websecure/myresolver)
- purge 0,5 m : worker/process et politique générale passés à 0,2 m seul
- intègre le travail parallèle non commité : export mosaïque multi-dalles
  (export.py + /api/export), sous-tuilage intégral des couches, légendes
  VIZ_LEGENDS, docs et tests associés (213 tests verts)
This commit is contained in:
Antoine Jacquin
2026-09-12 17:48:37 +02:00
parent 78a2c328c3
commit 68272cabf0
16 changed files with 1769 additions and 165 deletions

View File

@ -80,8 +80,8 @@ def test_missing_cells_includes_incomplete_tile(tmp_path):
assert [(t['col'], t['row']) for t in todo] == [(1054, 6882)]
def test_missing_cells_requires_both_resolutions(tmp_path):
"""Une tuile complète à 0.5 mais sans 0.2 reste à traiter."""
def test_missing_cells_requires_generation_resolution(tmp_path):
"""Une tuile complète à 0.5 mais sans 0.2 reste à traiter (seule 0.2 est générée)."""
from lidar_pipeline.webapp import missing_cells_with_corners
_make_tile(tmp_path, 1054, 6882, ["aspect"], resolutions=(0.5,))
assert len(missing_cells_with_corners([(1054, 6882)], tmp_path, viz=["aspect"])) == 1
@ -594,7 +594,7 @@ class _FakeRequest:
def test_generate_restricted_to_lan_cidr():
"""/api/generate n'est autorisé que depuis LIDAR_REGEN_CIDR (défaut 192.168.1.0/24)."""
"""/api/generate n'est autorisé que depuis LIDAR_REGEN_CIDR (si défini)."""
from fastapi import HTTPException
import lidar_pipeline.webapp as webapp
old = webapp.REGEN_CIDR
@ -639,6 +639,39 @@ def test_status_exposes_regen_allowed():
assert webapp.status(_FakeRequest(host="8.8.8.8"))["regen_allowed"] is False
def test_regen_cidr_default_covers_local_and_private():
"""Défaut : localhost + plages privées (LAN, hôte Docker), pas Internet."""
import lidar_pipeline.webapp as webapp
# Miroir du défaut de webapp.REGEN_CIDR (multidiffusion interdite ici :
# on le fixe explicitement pour tester la valeur de liste multi-CIDR).
old = webapp.REGEN_CIDR
webapp.REGEN_CIDR = "127.0.0.0/8,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
try:
for host in ("127.0.0.1", "::1", # boucle locale
"172.17.0.1", "172.26.0.5", # ponts Docker
"192.168.1.42", "192.168.122.7", # LAN privé
"10.0.0.5"):
assert webapp._ip_in_regen_cidr(host), host
for host in ("8.8.8.8", "2001:db8::1", "169.254.1.1", None):
assert not webapp._ip_in_regen_cidr(host), host
finally:
webapp.REGEN_CIDR = old
def test_regen_cidr_accepts_comma_separated_list():
"""LIDAR_REGEN_CIDR accepte plusieurs réseaux (entrées invalides ignorées)."""
import lidar_pipeline.webapp as webapp
old = webapp.REGEN_CIDR
webapp.REGEN_CIDR = "192.168.1.0/24, 10.0.0.0/8, pas-un-cidr"
try:
assert webapp._ip_in_regen_cidr("192.168.1.9")
assert webapp._ip_in_regen_cidr("10.1.2.3")
assert not webapp._ip_in_regen_cidr("192.168.3.9")
assert not webapp._ip_in_regen_cidr("172.17.0.1")
finally:
webapp.REGEN_CIDR = old
def test_auto_sync_once_skips_when_busy(monkeypatch):
"""Le cycle de cache ne lance rien si un rebuild tourne déjà."""
import time as _time