fix(ptica): нечисловое значение от OSRM/ORS больше не даёт 500 вместо деградации (#2464) #2944
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2944
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2464-routing-value-coercion"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Один и тот же пропуск в двух клиентах маршрутизации
Оба файла последовательно переводят любую кривизну ответа в доменную ошибку —
OsrmLocalUnavailableError/OrsUnavailableError, — потому что вызывающие ловят только её и уходят на прямолинейный fallback (parcels.py:399,poi_score.py:348).Конверсия значения была единственным исключением:
Голый
float()на нечисловом значении поднимаетValueErrorилиTypeError. Они пролетают мимо обработчиков и дают 500 на /analyze вместо деградации к прямолинейным расстояниям.Довод уже был написан — двумя строками ниже
В
ors_client, прямо под этим циклом:Автор рассуждал ровно про этот класс отказа и закрыл им проверку длины. К самой конверсии тот же принцип просто не применили.
Проверка
origin/maindistancesValueError: could not convert string to float: 'не число'distancesTypeError: float() argument must be a string or a real number, not 'dict'durationsValueErrordurationsTypeError: ... not 'list'Проверены оба типа исключения, а не только
ValueError:except ValueErrorв одиночку оставил бы половину дыры.Отдельный контроль:
nullв ответе — это «маршрут не построен», законныйNone, а не поломка. Зелёный с обеих сторон. Без него правка могла бы превратить легитимный пропуск в ошибку и «починить» тесты неверным способом.pytest poi_score + ors + osrm + analyze_osrm_distances: 54 passed, rc=0pytest tests/services: 3074 passed, 14 skipped, rc=0Прогон повторён после правок pre-commit, а не до.
Почему это не теория
Флаг
use_osrm_distancesвключён на проде (#39 A3), маршрутизация участвует в каждом/analyzeс POI. Ответ портится не «если сервер сойдёт с ума», а при любом рассогласовании версии OSRM-контейнера с ожидаемой формой ответа — ровно тот случай, ради которого весь остальной файл написан оборонительно.Refs #2464
Оба клиента маршрутизации переводят ЛЮБУЮ кривизну ответа в доменную ошибку (OsrmLocalUnavailableError / OrsUnavailableError), потому что вызывающие ловят только её и уходят на прямолинейный fallback: parcels.py:399 и poi_score.py:348. Конверсия значения была исключением из этого правила: out.append(float(d)) # osrm_client_local out.append(float(sec) / 60.0) # ors_client Голый float() на нечисловом значении поднимает ValueError или TypeError — они пролетают мимо обработчиков и дают 500 на /analyze вместо деградации к прямолинейным расстояниям. В ors_client довод уже был сформулирован ДВУМЯ СТРОКАМИ НИЖЕ: у проверки длины написано «иначе zip(strict=True) у вызывающего бросит ValueError (не OrsUnavailableError) → 500. Закрываем как ORS-сбой». Принцип верный, к самой конверсии его просто не применили. Тесты: 4 красных на origin/main с настоящими исключениями — `ValueError: could not convert string to float: 'не число'` и `TypeError: float() argument must be a string or a real number, not 'list'`. Проверены оба типа исключений, а не только ValueError. Контроль отдельно: null в ответе — это «маршрут не построен», законный None, а не поломка. Зелёный с обеих сторон, иначе правка могла бы превратить легитимный пропуск в ошибку. pytest poi_score + ors + osrm + analyze_osrm_distances: 54 passed, rc=0 pytest tests/services: 3074 passed, 14 skipped, rc=0 Прогон повторён после правок pre-commit ruff-format.