summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2013-03-07 16:16:58 -0600
committerDan McGee <dan@archlinux.org>2013-03-07 16:16:58 -0600
commit7a5b06c3e77b6369bf4c813dfc5a3c547cca2280 (patch)
tree569d4c543babaf008e71d4b02a4f1a996befc0bb
parentace95f6e53f41409568d4e4f1cf4c2a69d931e2c (diff)
Fix IntegrityError in corner case todolist update
We were seeing this in production: IntegrityError: duplicate key value violates unique constraint "todolists_todolistpackage_todolist_id_700d1b623414814c_uniq" DETAIL: Key (todolist_id, pkgname, arch_id)=(206, ruby-cairo, 2) already exists. This is due to a corner case where a package was originally on a todolist and the underlying package object disappeared, so the todolist entry was unlinked and pkg_id set to NULL. Later, this package came back, but our get_or_create tried to create an object that violated our unique constraint because of the missing pkg_id. Call get_or_create with the minimum necessary bits to find the todolist package object, and pass the rest of the values via defaults to avoid this problem. Additionally, relink any todolist entries up to a package in the repositories if one is available. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--todolists/views.py25
1 files changed, 19 insertions, 6 deletions
diff --git a/todolists/views.py b/todolists/views.py
index 36a0d97d..4b4a4dd2 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -176,16 +176,29 @@ def create_todolist_packages(form, creator=None):
# Add (or mark unremoved) any packages in the new packages list
todo_pkgs = []
for package in packages:
+ # ensure get_or_create uses the fields in our unique constraint
+ defaults = {
+ 'pkg': package,
+ 'pkgbase': package.pkgbase,
+ 'repo': package.repo,
+ }
todo_pkg, created = TodolistPackage.objects.get_or_create(
todolist=todolist,
- pkg=package, pkgname=package.pkgname,
- pkgbase=package.pkgbase,
- arch=package.arch, repo=package.repo)
+ pkgname=package.pkgname,
+ arch=package.arch,
+ defaults=defaults)
if created:
todo_pkgs.append(todo_pkg)
- elif todo_pkg.removed is not None:
- todo_pkg.removed = None
- todo_pkg.save()
+ else:
+ save = False
+ if todo_pkg.removed is not None:
+ todo_pkg.removed = None
+ save = True
+ if todo_pkg.pkg != package:
+ todo_pkg.pkg = package
+ save = True
+ if save:
+ todo_pkg.save()
return todo_pkgs