Repository navigation
Update the served current report when a PATCH names an outdated report ID - #4044
Conversation
…t ID GET serves an outdated report ID as the current report for the same simulations and year. PATCH now does the same, so the result a client saves under that ID completes the report it was served, instead of the outdated record. Fixes #4043. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4044 +/- ##
===========================================
+ Coverage 50.96% 87.82% +36.86%
===========================================
Files 242 258 +16
Lines 14527 15954 +1427
Branches 2334 2622 +288
===========================================
+ Hits 7403 14011 +6608
+ Misses 6501 1278 -5223
- Partials 623 665 +42 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Tested on MySQL as well as SQLite. I ran a local MySQL with the schema from I also replayed the production case with report 4729's real UK result (
The 500 from #3946 did not reproduce on MySQL either, so its cause is in production state or setup. It still needs the production log line "Unexpected error updating report #4729 for country uk". 🤖 Generated with Claude Code |
anth-volk
left a comment
There was a problem hiding this comment.
Approving: a PATCH that names an outdated report ID now resolves it the same way GET does, so the result reaches the report GET serves, and current IDs behave as before. Before merging, please make these four changes:
- Validate the requested ID, or take it from the record. The
PATCHroute passespayload.get("id")toupdate_report_outputunchanged, and the new code copies it intoresponse_id, whichReportOutputViewtypes asint | None. APATCHwith{"id": "1", …}for an outdated report returns"id": "1"as a string, while a current report returns the stored integer. Either check it asGETdoes (the integer check in_get_report_output), or setresponse_idfrom the outdated record's ownid. - Update the documentation. The
update_report_outputdocstring listsValueErroronly for the running-status and SPM-provenance cases. The new path can also raise it from_require_simulation, when an outdated record points to a simulation that no longer exists, and the route returns that as a 400. ThePATCH /{country_id}/reportroute docstring and its OpenAPI description still say the request updates the record with that ID, and theGETdescription doesn't say it can serve a different record. - Cover the other two cases the new path takes. The new tests use UK reports with
status="complete"only. Please add a test forstatus="error", which the app sends when a report fails, and one for a US economy report, where_update_report_outputchecks SPM provenance on the current record (#3946 is a US report). - Share the outdated-record setup. The steps that build an outdated record (set the
report_outputschema version to 2, compute the cache version, set it back to 3, insert aReportOutput) now appear three times: in the existing US test intest_report_output_service.py, in the newcreate_outdated_uk_reporthelper, and in the new route test, which also importsconstantsinside the test function. One shared helper or fixture would keep them consistent.
- Take response_id from the outdated record's own id, so a PATCH that sends the ID as a string still returns the stored integer. - Document the new ValueError (an outdated record whose simulation no longer exists) and the outdated-ID behaviour in the PATCH and GET route docstrings and OpenAPI descriptions. - Test status="error" on an outdated ID, and a US economy report on an outdated ID, with valid and missing SPM provenance. - Move the outdated-record setup to one helper, insert_outdated_report_output, used by all three tests that need it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Thanks @anth-volk. All four are in
Locally: |
anth-volk
left a comment
There was a problem hiding this comment.
Good to merge once CI passes
Fixes #4043
Related: #3946 (the 500 on the same
PATCH, not explained by this change).What and why
GET /{country_id}/report/{id}serves a report stored under an outdated report-output cache version as the current report for the same simulations and year, created if needed, with the requested ID asresponse_id.PATCH /{country_id}/reportselected the record by ID, so a client saving the result it was served wrote it to the outdated record, and the served report stayedpendingfor ever.ReportOutputService.update_report_outputnow resolves an outdated ID the wayresolve_report_outputdoes: it updates the current report for the same simulations and year (creating it if none was served yet), and the view keeps the requested ID asresponse_id, so the response'sidis the one the client sent. The outdated record is left as it is. Current IDs behave as before.This matters now because #4024 changed the cache version of every older v1 report (UK and US), so each one goes through this path the next time it opens.
Not covered
The 500 in #3946 (reports 4501 and 4729) does not reproduce on the SQLite test database, before or after this change. Its cause still needs the production log line "Unexpected error updating report #… for country …".
Overlap: #4029 (draft) also changes
PATCH /{country_id}/reportto keep complete results final. The two changes touch different parts ofupdate_report_output; whichever merges second needs a small rebase.Tests
test_update_with_outdated_id_completes_the_served_current_reportandtest_update_with_outdated_id_creates_the_current_report_when_none_was_served(service). Both fail onmaster.test_report_patch_with_outdated_id_completes_the_report_get_serves(route): GET, PATCH and GET again with the outdated ID.pytest tests/unit/test_simulation_and_report_routes.py tests/unit/services: 631 passed.ruff check,ruff format --checkandscripts/run_quality_guards.pypass (shellcheck not installed locally).No API contract change: the request and response shapes are unchanged.
🤖 Generated with Claude Code