Merge pull request #836 from taigaio/Fixing-deadlocks-on-update_attr_in_bulk_for_ids

Fixing deadlocks on update_attr_in_bulk_for_ids
remotes/origin/issue/4795/notification_even_they_are_disabled
David Barragán Merino 2016-10-04 18:23:10 +02:00 committed by GitHub
commit 7488878550
3 changed files with 20 additions and 8 deletions

View File

@ -18,11 +18,10 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import connection from django.db import connection
from django.db import DatabaseError
from django.db import transaction from django.db import transaction
from django.shortcuts import _get_queryset from django.shortcuts import _get_queryset
from django_pglocks import advisory_lock
from . import functions from . import functions
import re import re
@ -45,7 +44,7 @@ def get_object_or_none(klass, *args, **kwargs):
return None return None
def get_typename_for_model_class(model:object, for_concrete_model=True) -> str: def get_typename_for_model_class(model: object, for_concrete_model=True) -> str:
""" """
Get typename for model instance. Get typename for model instance.
""" """
@ -101,6 +100,7 @@ def save_in_bulk(instances, callback=None, precall=None, **save_options):
return ret return ret
@transaction.atomic @transaction.atomic
def update_in_bulk(instances, list_of_new_values, callback=None, precall=None): def update_in_bulk(instances, list_of_new_values, callback=None, precall=None):
"""Update a list of model instances. """Update a list of model instances.
@ -123,6 +123,7 @@ def update_in_bulk(instances, list_of_new_values, callback=None, precall=None):
callback(instance) callback(instance)
@transaction.atomic
def update_attr_in_bulk_for_ids(values, attr, model): def update_attr_in_bulk_for_ids(values, attr, model):
"""Update a table using a list of ids. """Update a table using a list of ids.
@ -147,7 +148,18 @@ def update_attr_in_bulk_for_ids(values, attr, model):
attr=attr) attr=attr)
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute(sql)
# We can have deadlocks with multiple updates over the same object
# In that situation we just retry
def _run_sql(retries=0, max_retries=3):
try:
cursor.execute(sql)
except DatabaseError:
print("retries", 0)
if retries < max_retries:
_run_sql(retries + 1)
transaction.on_commit(_run_sql)
def to_tsquery(term): def to_tsquery(term):
@ -230,10 +242,10 @@ def to_tsquery(term):
if not bit: if not bit:
continue continue
if bit.startswith('"') and bit.endswith('"') and len(bit)>2: if bit.startswith('"') and bit.endswith('"') and len(bit) > 2:
res.append(bit.replace('"', "'")) res.append(bit.replace('"', "'"))
else: else:
res.append("'%s':*" %(bit.replace("'", ""), )) res.append("'%s':*" % (bit.replace("'", ""), ))
res.append("&") res.append("&")

View File

@ -45,7 +45,7 @@ import pytest
from unittest import mock from unittest import mock
pytestmark = pytest.mark.django_db pytestmark = pytest.mark.django_db(transaction=True)
class ExpiredSigner(signing.TimestampSigner): class ExpiredSigner(signing.TimestampSigner):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -33,7 +33,7 @@ from taiga.projects.userstories import services, models
from .. import factories as f from .. import factories as f
import pytest import pytest
pytestmark = pytest.mark.django_db pytestmark = pytest.mark.django_db(transaction=True)
def test_get_userstories_from_bulk(): def test_get_userstories_from_bulk():