Rapatrier les tuiles manquantes depuis le serveur amont en mode cache seule
La maintenance de fond plafonne a LIDAR_TILE_BACKGROUND_MAX_Z (16 par defaut) : les zooms natifs 17-18 de l'interface restaient transparents sur une machine en cache seule. Une tuile absente du cache est desormais rapatriee de LIDAR_MAPS_URL (quelques dizaines de Ko, mise en cache, dedupliquee par verrou) sans aucun rendu local sur le chemin des requetes.
This commit is contained in:
@ -218,7 +218,11 @@ environment:
|
||||
- **`LIDAR_TILE_CACHE_ONLY=1`** — une tuile absente ou périmée est servie
|
||||
transparente avec `X-Tile-Pending: 1` et `Cache-Control: no-store` (le
|
||||
navigateur la redemande : dès que la maintenance l'a rendue, elle apparaît).
|
||||
Plus aucun rendu, ni rapatriement amont, sur le chemin des requêtes.
|
||||
Plus aucun rendu local sur le chemin des requêtes ; avec `LIDAR_MAPS_URL`,
|
||||
une tuile manquante (ex. zoom au-delà de `LIDAR_TILE_BACKGROUND_MAX_Z`)
|
||||
y est rapatriée — un téléchargement de quelques dizaines de Ko, mis en
|
||||
cache — puis servie : la navigation couvre tous les zooms sans jamais
|
||||
calculer sur la petite machine.
|
||||
- **`LIDAR_TILE_BACKGROUND=1`** — un sondeur rescane les dalles à intervalle
|
||||
régulier (`LIDAR_TILE_BACKGROUND_INTERVAL`, 120 s) ; chaque dalle nouvelle ou
|
||||
régénérée (le worker vient de produire, le cache à la demande vient de
|
||||
|
||||
@ -571,11 +571,30 @@ async def tile(layer: str, z: int, x: int, name: str, v: Optional[str] = None):
|
||||
raise HTTPException(404, "tuile hors grille")
|
||||
|
||||
if _env_flag("LIDAR_TILE_CACHE_ONLY"):
|
||||
# Mode cache seule : aucune navigation ne déclenche de rendu (ni amont).
|
||||
# Mode cache seule : aucune navigation ne déclenche de RENDU local.
|
||||
# Une tuile absente (ex. zoom > LIDAR_TILE_BACKGROUND_MAX_Z, jamais
|
||||
# couverte par la maintenance) est rapatriée du serveur amont
|
||||
# LIDAR_MAPS_URL — un simple téléchargement de quelques dizaines de
|
||||
# Ko, mis en cache, sans décodage ni calcul sur cette machine.
|
||||
data, state = await run_in_threadpool(
|
||||
tiles_mod.cached_tile, OUTPUT_DIR, layer, z, x, y, scale, fmt)
|
||||
pending = state == "pending"
|
||||
empty = state == "empty"
|
||||
if pending and MAPS_URL:
|
||||
suffix = "@2x" if scale == 2 else ""
|
||||
key = (layer, z, x, y, scale, fmt)
|
||||
entry = _acquire_lock(key)
|
||||
try:
|
||||
with entry[0]:
|
||||
data = _fetch_upstream(f"tiles/{layer}/{z}/{x}/{y}{suffix}.{fmt}")
|
||||
if data:
|
||||
tiles_mod._write_atomic(
|
||||
tiles_mod.tile_cache_path(OUTPUT_DIR, layer, z, x, y,
|
||||
scale, fmt), data)
|
||||
pending = False
|
||||
empty = False
|
||||
finally:
|
||||
_release_lock(key, entry)
|
||||
else:
|
||||
data = await run_in_threadpool(_tile_bytes, layer, z, x, y, scale, fmt)
|
||||
pending = False
|
||||
|
||||
@ -823,3 +823,36 @@ def test_ui_offers_generation_controls():
|
||||
assert "all_missing: true" in _MAP_JS
|
||||
# Fin de run : rafraîchissement des couches + relance de la maintenance
|
||||
assert "genAfterRun" in _MAP_JS and "api/map/background" in _MAP_JS
|
||||
|
||||
|
||||
def test_cache_only_fetches_missing_tile_upstream(tmp_path, monkeypatch):
|
||||
"""Cache seule + LIDAR_MAPS_URL : une tuile absente est rapatriee du serveur
|
||||
amont (aucun rendu local : les zooms au-dela de la maintenance s'affichent).
|
||||
"""
|
||||
import lidar_pipeline.mapserve as mapserve
|
||||
from lidar_pipeline import tiles
|
||||
_setup(tmp_path, monkeypatch)
|
||||
monkeypatch.setenv("LIDAR_TILE_CACHE_ONLY", "1")
|
||||
monkeypatch.setattr(mapserve, "MAPS_URL", "http://amont:8975")
|
||||
monkeypatch.setattr(mapserve, "_UPSTREAM", {"fails": 0, "until": 0.0})
|
||||
calls = []
|
||||
PNG = bytes([0x89, 0x50, 0x4E, 0x47, 13, 10, 0x1A, 10]) + b'TUILE-AMONT'
|
||||
|
||||
def fake_fetch(rel_path):
|
||||
calls.append(rel_path)
|
||||
return PNG
|
||||
|
||||
monkeypatch.setattr(mapserve, "_fetch_upstream", fake_fetch)
|
||||
try:
|
||||
z = 17 # jamais couvert par la maintenance (max_z 16 par defaut)
|
||||
x, y = _tile_of_cell(1054, 6882, z)
|
||||
resp = asyncio.run(mapserve.tile("aspect", z, x, f"{y}@2x.webp"))
|
||||
assert calls == [f"tiles/aspect/{z}/{x}/{y}@2x.webp"]
|
||||
assert resp.body == PNG
|
||||
assert resp.headers.get("X-Tile-Pending") != "1" # servie, plus en attente
|
||||
# Mise en cache : la seconde demande ne repasse pas par l'amont
|
||||
asyncio.run(mapserve.tile("aspect", z, x, f"{y}@2x.webp"))
|
||||
assert len(calls) == 1
|
||||
assert tiles.tile_cache_path(tmp_path, "aspect", z, x, y, 2, "webp").is_file()
|
||||
finally:
|
||||
monkeypatch.delenv("LIDAR_TILE_CACHE_ONLY")
|
||||
|
||||
Reference in New Issue
Block a user