Ne pas générer d overview locale sur la webapp légère (géométrie divergente du worker)

This commit is contained in:
Antoine Jacquin
2026-09-20 01:05:08 +02:00
parent b622d55720
commit 1d722ff10c
3 changed files with 41 additions and 7 deletions

View File

@ -1100,7 +1100,7 @@ def _collect_tile_metadata(tile, dtm_dir):
return meta
def build_index(output_dir, output_format='avif'):
def build_index(output_dir, output_format='avif', generate_overview=True):
"""Génère la carte interactive HTML des tuiles traitées, organisée par zones.
Scanne output_dir/visualisations/, collecte les métadonnées de génération,
@ -1110,6 +1110,10 @@ def build_index(output_dir, output_format='avif'):
Args:
output_dir: dossier de sortie racine (contient visualisations/).
output_format: format des images ('avif' ou 'webp') — pour info.
generate_overview: False sur la webapp légère (LIDAR_GENERATION_URL) :
ses mosaïques, bâties sur un cache partiel, auraient une géométrie
différente de celles du worker sous le même nom de fichier —
l'index distant fusionné après coup fournit les bonnes.
Returns:
Path vers index.html si succès, None si échec ou aucune tuile.
@ -1278,8 +1282,9 @@ def build_index(output_dir, output_format='avif'):
logger.info(f" {n_sous} sous-tuiles générée(s) pour {n_dalles} dalle(s)")
# Mosaïques d'overview (vue dézoomée) : une image par zone et par couche,
# assemblée depuis les vignettes des dalles de la zone.
overview = _build_overview(zone_records, output_dir)
# assemblée depuis les vignettes des dalles de la zone. Webapp légère :
# générées par la machine de traitement (cf. generate_overview).
overview = _build_overview(zone_records, output_dir) if generate_overview else {}
if overview:
n_items = sum(len(v['items']) for v in overview.values())
first = next(iter(overview.values()))['items'][0]

View File

@ -340,7 +340,7 @@ def test_rebuild_flag_synchronous(monkeypatch):
go = threading.Event()
def slow_build(out):
def slow_build(out, **kw):
go.wait(2) # rebuild artificiellement long
monkeypatch.setattr(index_mod, "build_index", slow_build)
@ -855,13 +855,38 @@ def test_available_layers_scans_disk(tmp_path, monkeypatch):
assert "aspect" not in layers
def test_local_rebuild_skips_overview(tmp_path, monkeypatch):
"""Webapp légère (GENERATION_URL) : pas de mosaïques d'overview locales.
Bâties sur un cache partiel, leur géométrie diffère (autre px/km, autre
étendue) de celles du worker sous le MÊME nom de fichier : plus récentes
(mtime), elles seraient servies à la place et désaligneraient le payload.
"""
import time
import lidar_pipeline.webapp as webapp
import lidar_pipeline.index as index_mod
monkeypatch.setattr(webapp, "OUTPUT_DIR", tmp_path)
monkeypatch.setattr(webapp, "GENERATION_URL", "http://distant:8973")
seen = {}
monkeypatch.setattr(index_mod, "build_index",
lambda out, **kw: seen.update(kw) or None)
webapp._rebuild.update({"running": False})
assert webapp._start_rebuild()["demarré"] is True
for _ in range(200):
if not webapp._rebuild["running"]:
break
time.sleep(0.02)
assert seen.get("generate_overview") is False
def test_rebuild_index_background(tmp_path, monkeypatch):
"""POST /api/rebuild lance build_index en arrière-plan puis termine."""
import time as _time
import lidar_pipeline.webapp as webapp
import lidar_pipeline.index as index_mod
calls = []
monkeypatch.setattr(index_mod, "build_index", lambda out: calls.append(out))
monkeypatch.setattr(index_mod, "build_index", lambda out, **kw: calls.append(out))
assert webapp.rebuild_index()["demarré"] is True
for _ in range(100):
if not webapp.rebuild_status()["running"]:
@ -1024,7 +1049,7 @@ def test_sync_is_rebuild_only(tmp_path, monkeypatch):
import lidar_pipeline.webapp as webapp
import lidar_pipeline.index as index_mod
calls = []
monkeypatch.setattr(index_mod, "build_index", lambda out: calls.append(out))
monkeypatch.setattr(index_mod, "build_index", lambda out, **kw: calls.append(out))
webapp._rebuild["done"] = None # ignore l'état d'un test précédent
assert webapp.sync_and_rebuild()["demarré"] is True
for _ in range(200):

View File

@ -1153,7 +1153,11 @@ def _start_rebuild():
def _run():
try:
from .index import build_index
build_index(OUTPUT_DIR)
# Overview : générée par la machine de traitement — une mosaïque
# locale (cache partiel, autre géométrie) sous le même nom de
# fichier serait servie à la place de la sienne (mtime plus
# récente) et désalignerait le payload distant.
build_index(OUTPUT_DIR, generate_overview=not GENERATION_URL)
# Mode deux machines : le rebuild local ne voit que le cache —
# on y fusionne l'index du worker pour que coquille embarquée et
# /api/tiles servent la même vue complète dès le 1er chargement.