fix: add retry and neighbor fallback for PLATEAU CityGML catalog API#208
fix: add retry and neighbor fallback for PLATEAU CityGML catalog API#208
Conversation
The PLATEAU Data Catalog API intermittently returns 404 for valid mesh codes, causing unfold-textured-by-id-and-mesh to fail even though search-by-address succeeded seconds earlier for the same mesh. Changes: - Add _query_plateau_catalog_api() helper with exponential backoff retry (max 2 retries, 0.5s/1.0s delays) for the catalog API call - Apply retry to both search and unfold code paths (DRY) - Add neighbor mesh fallback in search_building_by_id_and_mesh Step 3: when the primary mesh fetch fails after retries, try 8 neighboring meshes before returning error - Add 4 new regression tests covering retry logic and fetch-failure fallback (68 total tests pass) Closes #207
Deploying newlppaper-cad with
|
| Latest commit: |
4717899
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://f76e7b29.newlppaper-cad.pages.dev |
| Branch Preview URL: | https://fix-207-plateau-citygml-retr.newlppaper-cad.pages.dev |
Deploying paper-cad with
|
| Latest commit: |
4717899
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://60789c52.paper-cad.pages.dev |
| Branch Preview URL: | https://fix-207-plateau-citygml-retr.paper-cad.pages.dev |
There was a problem hiding this comment.
Pull request overview
Adds resiliency to PLATEAU CityGML catalog lookups to mitigate intermittent 404s that can break the “search → import/unfold” flow.
Changes:
- Introduces
_query_plateau_catalog_api()with exponential-backoff retries and reuses it from both search and fetch paths. - Adds Step 3 “neighbor mesh” fallback when the fetch itself fails for the primary mesh.
- Adds regression tests covering neighbor fallback behavior and retry exhaustion/success cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| backend/services/plateau_fetcher.py | Adds retry helper, wires it into catalog calls, and adds neighbor fallback when primary mesh fetch fails. |
| backend/tests/test_plateau_mesh_neighbor_fallback.py | Adds tests for Step 3 neighbor fallback and _query_plateau_catalog_api retry behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| # The primary mesh should have been tried first | ||
| called_meshes = [call.args[0] for call in mock_fetch.call_args_list] | ||
| assert called_meshes[0] == primary_mesh |
There was a problem hiding this comment.
This new regression test verifies Step 3 neighbor fallback success, but it doesn’t assert that the returned result["mesh_code"] reflects the neighbor mesh that actually supplied the CityGML (vs. the originally requested mesh). Adding that assertion would catch cases where the implementation fetches from a neighbor but still reports the primary mesh.
| assert called_meshes[0] == primary_mesh | |
| assert called_meshes[0] == primary_mesh | |
| # The mesh_code in the result should correspond to a neighbor that supplied CityGML | |
| neighbor_meshes = [m for m in called_meshes if m != primary_mesh] | |
| assert result["mesh_code"] in neighbor_meshes |
| for neighbor_mesh in neighboring_meshes: | ||
| fetched = _fetch_citygml_by_mesh_code_with_sources(neighbor_mesh) | ||
| if fetched: | ||
| logger.info( | ||
| f"[BUILDING SEARCH] ✓ CityGML found via neighboring mesh " | ||
| f"{neighbor_mesh} (primary {mesh_code} had no data)" | ||
| ) | ||
| break |
There was a problem hiding this comment.
Step 3 neighbor fallback can fetch CityGML from a neighboring mesh, but the function never records which mesh actually produced fetched. As a result, later resolved_mesh_code is initialized to the originally requested mesh_code, and the success response can report the wrong mesh_code even though the XML came from a neighbor. Track the mesh code used for the successful fetch (e.g., fetched_mesh_code) and use it to initialize resolved_mesh_code / searched mesh list.
| "error_details": ( | ||
| f"No CityGML data found for mesh code: {mesh_code} " | ||
| f"(also tried neighboring meshes)" | ||
| ), |
There was a problem hiding this comment.
error_details always says “(also tried neighboring meshes)”, but if get_neighboring_meshes_3rd() throws (or returns an empty list) no neighbors were actually tried. Consider building this message conditionally (or include how many/which meshes were attempted) so the error is accurate and more actionable.
Summary
背景
search-by-addressで建物検索が成功した直後にunfold-textured-by-id-and-meshを呼ぶと、同じメッシュコード (53394611) で PLATEAU API が 404 を返す現象が発生。外部 API の断続的な不安定性が原因。変更内容
リトライロジック (
_query_plateau_catalog_api)fetch_citygml_from_plateau) と展開パス (_fetch_citygml_by_mesh_code_with_sources) の両方で使用(DRY)近隣メッシュフォールバック (Step 3)
search_building_by_id_and_meshで初回メッシュフェッチが全リトライ後も失敗した場合、8つの隣接メッシュを試行テスト
test_fetch_failure_triggers_neighbor_fallback: Step 3 フォールバックの回帰テストtest_all_fetches_fail_returns_error_with_neighbor_details: 全フェッチ失敗時のエラーメッセージtest_query_plateau_catalog_api_retries_on_failure: リトライ成功のテストtest_query_plateau_catalog_api_returns_none_after_exhausting_retries: リトライ枯渇テストテスト結果
Closes #207