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>
This commit is contained in:
Dan McGee 2013-03-07 16:16:58 -06:00
parent ace95f6e53
commit 7a5b06c3e7

View File

@ -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