Project

General

Profile

Development #36028

traces en rapport à des notifs, "current database router prevents this relation."

Added by Frédéric Péters 5 days ago. Updated 3 days ago.

Status:
Solution déployée
Priority:
Normal
Target version:
-
Start date:
11 Sep 2019
Due date:
% Done:

0%

Patch proposed:
Yes
Planning:
No

Description

Traceback (most recent call last):
  File "/usr/bin/docbow-ctl", line 11, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
    utility.execute()
  File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 346, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 394, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 445, in execute
    output = self.handle(*args, **options)
  File "/usr/lib/python2.7/dist-packages/django/utils/decorators.py", line 145, in inner
    return func(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/docbow_project/docbow/management/commands/notify.py", line 12, in handle
    notification.process_notifications()
  File "/usr/lib/python2.7/dist-packages/docbow_project/docbow/notification.py", line 176, in process_notifications
    notifier=notifier.__class__)
  File "/usr/lib/python2.7/dist-packages/django_journal/journal.py", line 74, in error_record
    return record(tag, tpl, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django/utils/decorators.py", line 145, in inner
    return func(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django_journal/journal.py", line 58, in record
    journal.objectdata_set.create(tag=tag, content_object=value)
  File "/usr/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 756, in create
    return super(RelatedManager, self.db_manager(db)).create(**kwargs)
  File "/usr/lib/python2.7/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 346, in create
    obj = self.model(**kwargs)
  File "/usr/lib/python2.7/dist-packages/django/db/models/base.py", line 468, in __init__
    setattr(self, field.name, rel_obj)
  File "/usr/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 649, in __set__
    raise ValueError('Cannot assign "%r": the current database router prevents this relation.' % value)
ValueError: Cannot assign "<ContentType: notification>": the current database router prevents this relation.

0001-prevent-inconsistent-use-of-db-alias-36028.patch View (1007 Bytes) Emmanuel Cazenave, 11 Sep 2019 06:27 PM

0001-prevent-inconsistent-use-of-db-alias-36028.patch View (3.27 KB) Emmanuel Cazenave, 12 Sep 2019 11:01 AM

Associated revisions

Revision 1dca5156 (diff)
Added by Emmanuel Cazenave 4 days ago

prevent inconsistent use of db alias (#36028)

History

#1 Updated by Emmanuel Cazenave 4 days ago

  • Project changed from Parlement Wallon to Django Journal

C'est la fonction django_journal/journal.py::error_record qui plante (et stop net tout le traitement des notifications dans docbow au lieu de passer à la suivante).

Elle peut recevoir en argument n'importe quel objet dont des instances de django.db.models.Model. Ceux-ci sont marqués comme appartenant à une base de donnée, en pratique ici un objet appartenant à la DB désignée par 'défaut' dans la configuration.

Et dans error_record un hack pour effectuer quelques écritures sur la même base mais désignée sous un autre nom (ici 'journal' parce que JOURNAL_DB_FOR_ERROR_ALIAS='journal'), pour ne pas être pris dans la transaction courante.

def error_record(tag, tpl, **kwargs):
    '''Records error events.

       You must use this function when logging error events. It uses another
       database alias than the default one to be immune to transaction rollback
       when logging in the middle of a transaction which is going to
       rollback.
    '''
    if kwargs.get('using') is None:
        kwargs['using'] = getattr(settings, 'JOURNAL_DB_FOR_ERROR_ALIAS', 'default')

Et donc quelques lignes plus loin, on essaie d'établir une relation entre l'objet reçu dans la fonction et un objet créé après le hack :

if isinstance(value, django.db.models.Model):
    journal.objectdata_set.create(tag=tag, content_object=value)

(Pdb) value._state.db
'default'
(Pdb) journal._state.db
'journal'

Et donc logiquement django pas d'accord :

 
ValueError: Cannot assign "<ContentType: notification>": the current database router prevents this relation.

#2 Updated by Emmanuel Cazenave 4 days ago

Après le hack pour ne pas être pris dans la transaction, le hack pour défaire le premier hack si les circonstances l'exigent.

Pas le courage d'écrire le test unitaire (et sur l'idée qu'on pourrait plutôt se débarrasser de django-journal), mais testé en vrai.

#3 Updated by Emmanuel Cazenave 4 days ago

  • Private changed from Yes to No

#4 Updated by Benjamin Dauvergne 4 days ago

  • Status changed from Solution proposée to En cours

Par défaut GenericForeignKey.__set__() va chercher le ContentType dans la même db que l'objet posé et pas celui de l'objet créé1.

Pour passer outre faire :

journal.objectdata_set.create(tag=tag, content_type=ContentType.objects.using(using).get_for_model(value), object_id=value.pk)

Ça devrait marcher dans toutes les situations.

1 Voir https://github.com/django/django/blob/1.11.24/django/contrib/contenttypes/fields.py#L268 et
https://github.com/django/django/blob/1.11.24/django/contrib/contenttypes/fields.py#L162

#5 Updated by Emmanuel Cazenave 4 days ago

Yes beaucoup mieux (il fallait juste utiliser db_manager au lieu de using sur ContentType.objects). Et un test.

#6 Updated by Benjamin Dauvergne 3 days ago

  • Status changed from Solution proposée to Solution validée
  • Assignee set to Emmanuel Cazenave

#7 Updated by Emmanuel Cazenave 3 days ago

  • Status changed from Solution validée to Résolu (à déployer)
ommit 1dca515624f3b9e4c8a6727c011a8d2c6fa5ae54
Author: Emmanuel Cazenave <ecazenave@entrouvert.com>
Date:   Wed Sep 11 18:22:07 2019 +0200

    prevent inconsistent use of db alias (#36028)

#8 Updated by Emmanuel Cazenave 3 days ago

  • Status changed from Résolu (à déployer) to Solution déployée

Also available in: Atom PDF