fix(p3-batch): восстановление 13 Fable 5 P3-fixes из lost branches #1301
1 changed files with 49 additions and 26 deletions
|
|
@ -126,6 +126,11 @@ def _way_to_polygon_wkt(nodes: list[dict]) -> str | None:
|
|||
|
||||
Используется для natural=water (озёра, пруды). Если кольцо не замкнуто
|
||||
автоматически — добавляем первую точку в конец.
|
||||
|
||||
PostGIS отвергает linear ring < 4 точек. Замкнутый way из 3 точек
|
||||
[A, B, A] (points[0]==points[-1]) даёт POLYGON((A,B,A)) — "geometry
|
||||
requires more points". Возвращаем None, чтобы caller сделал fallback
|
||||
на LineString или пропустил элемент.
|
||||
"""
|
||||
points = [f"{n['lon']} {n['lat']}" for n in nodes if "lon" in n and "lat" in n]
|
||||
if len(points) < 3:
|
||||
|
|
@ -133,6 +138,9 @@ def _way_to_polygon_wkt(nodes: list[dict]) -> str | None:
|
|||
# Замкнуть кольцо если нужно
|
||||
if points[0] != points[-1]:
|
||||
points.append(points[0])
|
||||
# Итоговое кольцо должно содержать ≥4 точек (PostGIS требование).
|
||||
if len(points) < 4:
|
||||
return None
|
||||
return f"POLYGON(({', '.join(points)}))"
|
||||
|
||||
|
||||
|
|
@ -203,35 +211,50 @@ def sync_noise_sources_to_db() -> dict[str, int]:
|
|||
**geom_params,
|
||||
}
|
||||
|
||||
result = db.execute(
|
||||
text(f"""
|
||||
INSERT INTO osm_noise_sources_ekb
|
||||
(osm_type, osm_id, source_type, road_class, name, geom, tags, fetched_at)
|
||||
VALUES (
|
||||
:osm_type, :osm_id, :source_type, :road_class, :name,
|
||||
{geom_sql},
|
||||
CAST(:tags AS jsonb), NOW()
|
||||
)
|
||||
ON CONFLICT (osm_type, osm_id) DO UPDATE
|
||||
SET source_type = EXCLUDED.source_type,
|
||||
road_class = EXCLUDED.road_class,
|
||||
name = EXCLUDED.name,
|
||||
geom = EXCLUDED.geom,
|
||||
tags = EXCLUDED.tags,
|
||||
fetched_at = NOW()
|
||||
RETURNING (xmax = 0) AS is_insert
|
||||
"""),
|
||||
params,
|
||||
).scalar()
|
||||
|
||||
if result:
|
||||
inserted += 1
|
||||
else:
|
||||
updated += 1
|
||||
try:
|
||||
with db.begin_nested(): # SAVEPOINT — откат только этой записи
|
||||
result = db.execute(
|
||||
text(f"""
|
||||
INSERT INTO osm_noise_sources_ekb
|
||||
(osm_type, osm_id, source_type, road_class, name, geom, tags,
|
||||
fetched_at)
|
||||
VALUES (
|
||||
:osm_type, :osm_id, :source_type, :road_class, :name,
|
||||
{geom_sql},
|
||||
CAST(:tags AS jsonb), NOW()
|
||||
)
|
||||
ON CONFLICT (osm_type, osm_id) DO UPDATE
|
||||
SET source_type = EXCLUDED.source_type,
|
||||
road_class = EXCLUDED.road_class,
|
||||
name = EXCLUDED.name,
|
||||
geom = EXCLUDED.geom,
|
||||
tags = EXCLUDED.tags,
|
||||
fetched_at = NOW()
|
||||
RETURNING (xmax = 0) AS is_insert
|
||||
"""),
|
||||
params,
|
||||
).scalar()
|
||||
if result:
|
||||
inserted += 1
|
||||
else:
|
||||
updated += 1
|
||||
except Exception as e:
|
||||
# Дефектный way (например, 3-точечное замкнутое кольцо POLYGON((A,B,A))
|
||||
# отвергается PostGIS) не должен валить весь weekly-sync. SAVEPOINT
|
||||
# откатывает только эту строку, продолжаем с остальными.
|
||||
logger.warning(
|
||||
"noise_sync insert failed for %s/%s (source_type=%s): %s",
|
||||
osm_type,
|
||||
osm_id,
|
||||
source_type,
|
||||
e,
|
||||
)
|
||||
skipped += 1
|
||||
|
||||
db.commit()
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.exception("noise_sync: unexpected error, outer tx rolled back: %s", e)
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue