parsemail: fix SeriesReference race with concurrent delivery
When multiple parsemail processes run in parallel (e.g. postfix
delivering several messages from the same series at once), two
processes can try to create a SeriesReference for the same msgid
simultaneously. The second one fails with an IntegrityError:
django.db.utils.IntegrityError: duplicate key value violates
unique constraint "patchwork_seriesreference_project_id_msgid_..."
DETAIL: Key (project_id, msgid)=(2, <...>) already exists.
This can result in incomplete series that never reach the
"received_all" state because the failed parsemail invocation
prevents one of the patches from being recorded.
The existing get/create pattern has a classic TOCTOU race: the get
succeeds (no reference found), but by the time create runs, another
process has already inserted the row. Replace both the try/get/
except/create block and the bare create call with get_or_create
which handles the race atomically at the database level.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviwed-by: Stephen Finucane <stephen@that.guru>
(cherry picked from commit
3558907533a1a420ccceec6935635e7c2245eb69)