Retry interrupted thematic WCS tiles
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-16 04:46:13 +02:00
parent 6a7fa57463
commit 791548e332
2 changed files with 87 additions and 24 deletions
@@ -1,5 +1,6 @@
from __future__ import annotations
from http.client import IncompleteRead
from pathlib import Path
from types import SimpleNamespace
from uuid import uuid4
@@ -89,6 +90,11 @@ class FakeResponse:
return self.content[:limit]
class IncompleteResponse(FakeResponse):
def read(self, limit: int):
raise IncompleteRead(self.content[:limit])
def payload(product_key: str = "space_occupation_2025", *, side_m: float = 1000.0) -> ThematicRasterAcquireRequest:
transformer = Transformer.from_crs("EPSG:31370", "EPSG:4326", always_xy=True)
min_x, min_y = transformer.transform(200_000, 210_000)
@@ -171,6 +177,52 @@ def test_complete_kempen_scope_fits_the_tiled_thematic_guardrails() -> None:
assert exc_info.value.code == "THEMATIC_RASTER_SELECTION_TOO_LARGE"
def test_wcs_fetch_retries_an_incomplete_tile_without_accepting_partial_bytes(monkeypatch) -> None:
content = b"II*\x00complete-geotiff"
responses = [IncompleteResponse(content), FakeResponse(content)]
attempts = 0
def opener(*_args, **_kwargs):
nonlocal attempts
response = responses[attempts]
attempts += 1
return response
monkeypatch.setattr("app.services.thematic_raster_acquisition_service.time.sleep", lambda _seconds: None)
result, content_type = ThematicRasterAcquisitionService._fetch(
"https://example.invalid/wcs",
Settings(_env_file=None),
opener,
)
assert attempts == 2
assert result == content
assert content_type == "image/tiff"
def test_wcs_fetch_fails_closed_after_bounded_incomplete_tile_retries(monkeypatch) -> None:
attempts = 0
def opener(*_args, **_kwargs):
nonlocal attempts
attempts += 1
return IncompleteResponse(b"II*\x00partial")
monkeypatch.setattr("app.services.thematic_raster_acquisition_service.time.sleep", lambda _seconds: None)
with pytest.raises(AppError) as exc_info:
ThematicRasterAcquisitionService._fetch(
"https://example.invalid/wcs",
Settings(_env_file=None),
opener,
)
assert attempts == ThematicRasterAcquisitionService.WCS_FETCH_ATTEMPTS
assert exc_info.value.code == "THEMATIC_RASTER_PROVIDER_UNAVAILABLE"
assert exc_info.value.details["attempts"] == 3
def test_binary_and_normalized_products_fail_closed_on_invalid_values() -> None:
binary = ThematicRasterAcquisitionService._product("space_occupation_2025")
score = ThematicRasterAcquisitionService._product("service_level_2022")