Open sentry-io[bot] opened 3 years ago
Discord: https://discord.com/channels/799147121357881364/813861006718926848/858057432592941136
Ugaso tracked it to this report https://vial.calltheshots.us/admin/core/report/35224/change/ on this location: https://vial.calltheshots.us/admin/core/location/8234/history/
Here's the method with the failing assertion: https://github.com/CAVaccineInventory/vial/blob/cdaaab053a9cf1cef40104a2cdf480b7932d58f7/vaccinate/core/models.py#L1125-L1146
And here's where it's being called with a location that doesn't correctly match: https://github.com/CAVaccineInventory/vial/blob/cdaaab053a9cf1cef40104a2cdf480b7932d58f7/vaccinate/core/exporter/__init__.py#L248-L271
So it looks like latest = location.dn_latest_non_skip_report
is somehow returning a report that points to a different location.
select location.id, report.location_id
from location join report on location.dn_latest_non_skip_report_id = report.id
where location.id != report.location_id
This query should never return any results... but it's returning 318!
Here's the full list of affected locations:
... and every single one of those pages is a 500 error right now.
All of those locations are soft-deleted: https://vial.calltheshots.us/dashboard/?sql=select+%27-+https%3A%2F%2Fvial.calltheshots.us%2Fadmin%2Fcore%2Flocation%2F%27+%7C%7C+location.id%2C+location.soft_deleted%0D%0Afrom+location+join+report+on+location.dn_latest_non_skip_report_id+%3D+report.id%0D%0Awhere+location.id+%21%3D+report.location_id%3A7RxSdnUXmC7u-ohRq3i29eX4EVlsch6eZ6d582VIMF4
select '- https://vial.calltheshots.us/admin/core/location/' || location.id, location.soft_deleted
from location join report on location.dn_latest_non_skip_report_id = report.id
where location.id != report.location_id
This was caused by merges. All but one of those 318 events has a populated duplicate_of_id
column - so they were merged, but the dn_latest_non_skip_report_id
column on the loser of the merge was not recalculated.
[ Need to figure out what's going on with the single location that wasn't the loser of a merge - https://vial.calltheshots.us/dashboard/?sql=select+location.id%2C+location.soft_deleted%2C+location.duplicate_of_id%2C+location.dn_latest_non_skip_report_id%2C+report.id+as+report_id%2C+report.location_id+as+report_location_id%0D%0Afrom+location+join+report+on+location.dn_latest_non_skip_report_id+%3D+report.id%0D%0Awhere+location.id+%21%3D+report.location_id%0D%0Aand+duplicate_of_id+is+null%3AIhGCoZ7Qpa2nlkCAxZT9ebxootYQihvKnHlXVqlPqa8 shows that to be 8038 which isn't soft-deleted either)
Looks like that one had a manual edit which broke the data model somehow: https://vial.calltheshots.us/admin/core/location/8038/history/compare/?version_id2=217907&version_id1=217877
Aha! The 317 locations here are a red-herring - the export script only considers not-soft-deleted locations, so they're not causing the error with the Mapbox export.
The location that is breaking things is the one @ugaso identified, https://vial.calltheshots.us/admin/core/location/8234/history/
It looks to me like https://vial.calltheshots.us/admin/core/location/8038/history/ is the corrupt location: it was merged into https://vial.calltheshots.us/admin/core/location/8234/ BUT a later edit in the admin tool reverted those soft_deleted and duplicate_of fields back to their pre-merged state - even though the reports had been copied across.
That edit happened within an hour of the merge. My best guess is that someone had left a tab open with the edit form for that location, then when they hit "save" later it over-wrote the data from the merge.
I think I can fix that manually now (I'll re-run the merge) - then I'll make the duplicate_of field read-only in the admin to avoid this happening again in the future.
Re-running the merge using https://vial.calltheshots.us/admin/merge-locations/?winner=ldbdr&loser=lczkk
There are now zero non-soft-deleted locations with mismatching location IDs against their denormalized report IDs: https://vial.calltheshots.us/dashboard/?sql=select+location.id%2C+location.soft_deleted%2C+location.duplicate_of_id%2C+location.dn_latest_non_skip_report_id%2C+report.id+as+report_id%2C+report.location_id+as+report_location_id%0D%0Afrom+location+join+report+on+location.dn_latest_non_skip_report_id+%3D+report.id%0D%0Awhere+location.id+%21%3D+report.location_id%0D%0Aand+duplicate_of_id+is+null%3AIhGCoZ7Qpa2nlkCAxZT9ebxootYQihvKnHlXVqlPqa8
Re-ran the mapbox export by clicking the button in https://console.cloud.google.com/cloudscheduler?project=django-vaccinateca
It ran successfully.
To avoid this happening in the future, I'm going to do two things:
duplicate_of
a read-only column, which can only be edited using the merge locations toolsoft_deleted
column for locations that have a duplicate_of
value.It looks to me like https://vial.calltheshots.us/admin/core/location/8038/history/ is the corrupt location: it was merged into https://vial.calltheshots.us/admin/core/location/8234/ BUT a later edit in the admin tool reverted those soft_deleted and duplicate_of fields back to their pre-merged state - even though the reports had been copied across.
TY for solving this! What an interesting bug.
How were you able to track the merge history of that location? I found it! Merged location dashboard details this well: https://vial.calltheshots.us/dashboard/merged-locations/
Sentry Issue: VIAL-BR