Fusionner l'index du worker dans la coquille au rebuild (1er chargement complet)
- Sur la webapp légère, le rebuild ne voyait que le cache local : la coquille HTML embarquait un sous-ensemble des tuiles et le premier chargement n'affichait pas les tuiles récentes du worker — elles n'arrivaient qu'au sondage /api/tiles suivant (15 s). - _merge_remote_index() applique au rebuild la même fusion que /api/tiles (l'index distant prime, le local complète) et réécrit index_tiles.json ET la liste embarquée dans index.html. - AGENTS.md : avertissement — le Pi de prod tourne en compose+override (labels Traefik + /srv/lidar/output), jamais via serve-webapp.sh.
This commit is contained in:
@ -999,6 +999,59 @@ def tiles_data(stamp: Optional[float] = None):
|
||||
_rebuild = {"running": False, "error": None, "done": None, "phase": None}
|
||||
|
||||
|
||||
def _merge_remote_index():
|
||||
"""Fusionne l'index du worker dans index_tiles.json et la coquille HTML.
|
||||
|
||||
Le rebuild local ne voit que le cache : sans fusion, la coquille embarque
|
||||
un sous-ensemble des tuiles (celles déjà rapatriées) et le premier
|
||||
chargement de la carte n'affiche pas les tuiles récentes du worker —
|
||||
elles n'arrivent qu'au sondage /api/tiles qui suit. Mêmes règles que
|
||||
tiles_data : l'index distant prime (tuiles régénérées), le local complète
|
||||
les positions que le worker n'a plus (historique).
|
||||
"""
|
||||
remote = _remote_tiles_data() # frais : _start_rebuild a vidé le cache
|
||||
if not remote or not remote.get("tiles"):
|
||||
return
|
||||
path = OUTPUT_DIR / "index_tiles.json"
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, ValueError):
|
||||
data = {}
|
||||
merged = list(remote["tiles"])
|
||||
keys = {_tile_entry_key(t) for t in merged}
|
||||
for t in data.get("tiles") or []:
|
||||
k = _tile_entry_key(t)
|
||||
if k not in keys:
|
||||
merged.append(t)
|
||||
keys.add(k)
|
||||
viz_meta = dict(data.get("viz_meta") or {})
|
||||
viz_meta.update(remote.get("viz_meta") or {})
|
||||
from .index import PANEL_VIZ
|
||||
if PANEL_VIZ is not None:
|
||||
allowed = set(PANEL_VIZ)
|
||||
viz_meta = {k: v for k, v in viz_meta.items() if k in allowed}
|
||||
path.write_text(json.dumps({
|
||||
"tiles": merged,
|
||||
"viz_meta": viz_meta,
|
||||
"stats": remote.get("stats") or data.get("stats") or {},
|
||||
}, ensure_ascii=False), encoding="utf-8")
|
||||
# Coquille HTML : la liste embarquée doit être la même (fusionnée). Le
|
||||
# JSON ne contient jamais de « ; » : la première séquence « ]; » après
|
||||
# « const TILES = [ » termine forcément l'instruction.
|
||||
html_path = OUTPUT_DIR / "index.html"
|
||||
try:
|
||||
html = html_path.read_text(encoding="utf-8")
|
||||
new_html = re.sub(r"const TILES = \[.*?\];",
|
||||
"const TILES = " + json.dumps(merged, ensure_ascii=False) + ";",
|
||||
html, count=1, flags=re.S)
|
||||
if new_html != html:
|
||||
html_path.write_text(new_html, encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
logger.info(f"Index fusionné avec la machine de traitement : "
|
||||
f"{len(merged)} tuile(s) au total")
|
||||
|
||||
|
||||
def _start_rebuild():
|
||||
"""Lance en arrière-plan le rebuild de l'index (vignettes + carte).
|
||||
|
||||
@ -1021,6 +1074,14 @@ def _start_rebuild():
|
||||
try:
|
||||
from .index import build_index
|
||||
build_index(OUTPUT_DIR)
|
||||
# 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.
|
||||
if GENERATION_URL:
|
||||
try:
|
||||
_merge_remote_index()
|
||||
except Exception as e: # noqa: BLE001 — index local valable
|
||||
logger.warning(f"Fusion de l'index distant ignorée : {e}")
|
||||
except Exception as e: # noqa: BLE001 — remonté à l'UI via l'état
|
||||
_rebuild["error"] = str(e)
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user