Skip to content

Commit e0d7e45

Browse files
committed
fix(water-level-import): handle savepoint initialization failure gracefully
- Move `begin_nested` savepoint call inside the try block for proper error handling. - Ensure session expiration when savepoint creation fails. - Add test coverage for savepoint creation failure scenarios.
1 parent 9741d41 commit e0d7e45

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

services/water_level_csv.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,9 @@ def _create_records(
351351
errors: list[str] = []
352352

353353
for row in rows:
354-
savepoint = session.begin_nested()
354+
savepoint = None
355355
try:
356+
savepoint = session.begin_nested()
356357
sample_name = _build_sample_name(row)
357358
sample = _find_existing_imported_sample(session, row, sample_name)
358359

@@ -406,7 +407,7 @@ def _create_records(
406407
}
407408
)
408409
except Exception as exc: # pragma: no cover - exercised via DB tests
409-
if savepoint.is_active:
410+
if savepoint is not None and savepoint.is_active:
410411
savepoint.rollback()
411412
else:
412413
session.expire_all()

tests/test_water_level_csv_service.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from tests import get_parameter_id
99
from services.water_level_csv import (
1010
_build_sample_name,
11+
_create_records,
1112
_resolve_measuring_point_height,
1213
_validate_depth_to_water_against_well,
1314
bulk_upload_water_levels,
@@ -116,6 +117,30 @@ def test_build_sample_name_uses_deterministic_well_inventory_style_format():
116117
assert _build_sample_name(row) == "AR0001-WL-202502151030"
117118

118119

120+
def test_create_records_reports_savepoint_creation_failure_as_row_error():
121+
class BrokenSession:
122+
def __init__(self):
123+
self.expire_all_called = False
124+
125+
def begin_nested(self):
126+
raise RuntimeError("savepoint failed")
127+
128+
def expire_all(self):
129+
self.expire_all_called = True
130+
131+
session = BrokenSession()
132+
133+
created, errors = _create_records(
134+
session,
135+
parameter_id=1,
136+
rows=[SimpleNamespace(row_index=7)],
137+
)
138+
139+
assert created == []
140+
assert errors == ["Row 7: savepoint failed"]
141+
assert session.expire_all_called is True
142+
143+
119144
def test_bulk_upload_water_levels_is_idempotent(water_well_thing):
120145
csv_content = "\n".join(
121146
[

0 commit comments

Comments
 (0)