fix(objective parser): use_float=True in ijson + default=str in json.dumps

ijson по умолчанию (use_float=False) возвращает все numeric values
как Decimal. _row_to_lot строит raw_props через json.dumps(row, ...)
— stdlib json не сериализует Decimal → TypeError → inner try/except
swallows exception → run завершается status=done, lots=0.

Двойной fix:
1. ijson.items(stream, "result.item", use_float=True) в обоих
   parse_lots_pf_stream — все numerics приходят как float (укладывается
   в float64 precision для финансовых сумм / площадей).
2. json.dumps(..., default=str) в обоих _row_to_lot и
   _row_to_corp_room_month — defense in depth для любых exotic типов.

Glitchtip BACKEND-1L (release d1b721a, firstSeen 18:58:48Z) — silent
fail после успешного streaming в PR #318 fixup.
This commit is contained in:
lekss361 2026-05-17 22:07:40 +03:00
parent d1b721a3be
commit ecbdcf35fb

View file

@ -206,7 +206,7 @@ def _row_to_corp_room_month(row: dict, group_name: str, raw_id: int | None) -> d
),
# Audit
"raw_id": raw_id,
"raw_props": json.dumps(row, ensure_ascii=False),
"raw_props": json.dumps(row, ensure_ascii=False, default=str),
}
@ -342,7 +342,7 @@ def _row_to_lot(row: dict, raw_id: int | None, snapshot_date: date) -> dict:
"encumbrance_start_date": _parse_iso_date(row.get("Дата начала обременения")),
"egrn_actual_date": _parse_iso_date(row.get("Дата актуальности данных из ЕГРН")),
"raw_id": raw_id,
"raw_props": json.dumps(row, ensure_ascii=False),
"raw_props": json.dumps(row, ensure_ascii=False, default=str),
"snapshot_date": snapshot_date,
}
@ -543,7 +543,7 @@ def parse_lots_pf_stream(
history_batch: list[dict] = []
batches_since_commit = 0
for row in ijson.items(stream, "result.item"):
for row in ijson.items(stream, "result.item", use_float=True):
if not isinstance(row, dict):
continue
params = _row_to_lot(row, raw_id, snapshot_date)
@ -712,7 +712,7 @@ def parse_lots_pf_stream(
db.execute(_LOTS_HISTORY_INSERT, history_batch)
batch = []
for row in ijson.items(stream, "result.item"):
for row in ijson.items(stream, "result.item", use_float=True):
if not isinstance(row, dict):
continue
params = _row_to_lot(row, raw_id, snapshot_date)