]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
parsemail: wrap parse_mail() in a single transaction main
authorRobin Jarry <robin@jarry.cc>
Mon, 8 Jun 2026 11:59:43 +0000 (13:59 +0200)
committerStephen Finucane <stephen@that.guru>
Wed, 10 Jun 2026 12:12:31 +0000 (13:12 +0100)
Wrap the entire parse_mail() call in transaction.atomic() so that all
database writes from email parsing run inside a single transaction.
The existing transaction.atomic() blocks inside parse_mail() become
savepoints within this outer transaction. The series deduplication
retry logic continues to work since savepoint rollbacks are scoped
to their own savepoint.

This also ensures that any on_commit() callbacks registered by signal
handlers only fire after the full email has been parsed and all
patch/series associations are committed.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Signed-off-by: Stephen Finucane <stephen@that.guru>
Reviewed-by: Stephen Finucane <stephen@that.guru>
[stephenfin: Slight tweaks to the release notes]

patchwork/management/commands/parsemail.py
releasenotes/notes/parsemail-transaction-d4e5f6g7h8i9j0k1.yaml [new file with mode: 0644]

index bcb257fe971421720acbb41dcbed1f7bc2265b37..2f90047a991b96db4937d72cc9442f115b425809 100644 (file)
@@ -8,6 +8,7 @@ import logging
 import sys
 
 from django.core.management import base
+from django.db import transaction
 
 from patchwork.parser import parse_mail
 from patchwork.parser import DuplicateMailError
@@ -57,7 +58,8 @@ class Command(base.BaseCommand):
         # broken email (ValueError):   1 (this could be noisy, if it's an issue
         #                                 we could use a different return code)
         try:
-            result = parse_mail(mail, options['list_id'])
+            with transaction.atomic():
+                result = parse_mail(mail, options['list_id'])
             if result is None:
                 logger.warning('Nothing added to database')
         except DuplicateMailError as exc:
diff --git a/releasenotes/notes/parsemail-transaction-d4e5f6g7h8i9j0k1.yaml b/releasenotes/notes/parsemail-transaction-d4e5f6g7h8i9j0k1.yaml
new file mode 100644 (file)
index 0000000..5a224ca
--- /dev/null
@@ -0,0 +1,6 @@
+---
+fixes:
+  - |
+    Wrap the entire ``parse_mail()`` function in a single database
+    transaction to prevent partial state from being visible to
+    concurrent readers.