PR #260 second-opinion review 🔴 BLOCK → fixes: 1. nspd_bulk_client.py: _SEMAPHORE module-level → per-instance self._sem создаётся в __aenter__ под текущий event loop. Sequential asyncio.run() в search_by_quarter (11 layers × asyncio.run() per layer) bind'ил module-level semaphore к first loop'у → RuntimeError на втором вызове → все cells return_exceptions=True проглатывали → grid возвращал 0 features. 2. nspd_sync.py: harvest_quarter добавлен time_limit=900 (hard) рядом с soft_time_limit=600. Safety net если task игнорит SoftTimeLimitExceeded. 3. tests/test_nspd_client.py: добавлен _make_fake_grid_walk helper + monkeypatch NSPDClient.get_features_in_bbox_grid в 3 тестах (search_by_quarter_core_only / _with_zouit / _layers_fetched_with_risks). Без этого area layers били бы по живому NSPD API → CI flaky. Tests: 37 passed, 1 skipped (3 area-dispatch + 34 grid-walk). |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| ekburg_permits_sync.py | ||
| noise_sync.py | ||
| nspd_denorm_backfill.py | ||
| nspd_geo.py | ||
| nspd_sync.py | ||
| objective_etl.py | ||
| poi_sync.py | ||
| pzz_sync.py | ||
| refresh_analytics.py | ||
| scrape_cadastre.py | ||
| scrape_kn.py | ||
| scrape_objective.py | ||