Project

General

Profile

Développement #47916

Incohérences lors de la duplication d'un guichet avec des sources d'exceptions

Added by Valentin Deniaud about 4 years ago. Updated about 4 years ago.

Status:
Fermé
Priority:
Normal
Category:
-
Target version:
-
Start date:
21 October 2020
Due date:
% Done:

0%

Estimated time:
Patch proposed:
Yes
Planning:
No

Description

Sens, chaque exception est en double et la source est en double : https://agendas.demarches.ville-sens.fr/manage/agendas/56/settings

Essonne, chaque exception est en double, une seule source, le doublon a perdu son attribut « source » et son flag « external » : https://agendas.demarches.essonne.fr/manage/agendas/1/settings

Je regarde...


Files

Associated revisions

Revision f880490e (diff)
Added by Valentin Deniaud about 4 years ago

agendas: set proper exception source when duplicating (#47916)

Revision bb3e011b (diff)
Added by Valentin Deniaud about 4 years ago

agendas: do not import exception from settings when duplicating (#47916)

Revision c1d5eb32 (diff)
Added by Valentin Deniaud about 4 years ago

agendas: add unicity constraint on exception source slug (#47916)

History

#1

Updated by Valentin Deniaud about 4 years ago

Et donc le coupable, « Copier le paramétrage du guichet »...

En plus du patch pour éviter cette duplication, il va falloir une migration qui ajoute une contrainte d'unicité sur le slug de la source d'exception, et vire les doublons au préalable.

#2

Updated by Valentin Deniaud about 4 years ago

Side effect, ça fait des exceptions qu'on ne peut plus désactiver, #47915.

#3

Updated by Valentin Deniaud about 4 years ago

0001 pour fixer le bug, 0002 pour réparer les db et rajouter une contrainte pour être sûr que ça n'arrive plus...

La migration de 0002 doit se faire en deux fois, parce que une migration = un bloc atomic, et que django ne peut pas bouger les données et ajouter des contraintes au champs en même temps (erreur « pending trigger events »). En vrai c'est pas fou, on aimerait bien de l'atomicité, je m'y repenche demain.

#4

Updated by Valentin Deniaud about 4 years ago

Valentin Deniaud a écrit :

je m'y repenche demain.

C'est un comportement documenté et je n'ai pas l'impression qu'il y ait de contournement, https://docs.djangoproject.com/en/1.11/ref/migration-operations/#django.db.migrations.operations.RunPython :

you should avoid combining schema changes and RunPython operations in the same migration or you may hit errors like OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events

Mais en fait c'est un faux problème que je me posais : comme la première migration assure l'unicité, et que la deuxième ajoute la contrainte, je me disais qu'un doublon pouvait très hypothétiquement être créé dans l'intervalle et faire échouer le truc. Mais un doublon ne peut plus être créé, c'est assuré par le premier patch. Donc tout va bien.

#5

Updated by Valentin Deniaud about 4 years ago

  • Status changed from Solution proposée to En cours
Info pour qui relira, tapé sur le salon, à propos de 0001 :
Il y a deux trucs à corriger
  • ne pas importer les exceptions si on est dans un cas de duplication (et laisser ensuite la duplication de source se faire, on pourrait faire le choix inverse mais ça serait moins clair)
  • ne pas dupliquer les exceptions externes, parce qu'elles sont liées à la source du guichet initial et on veut pas ça

Et en tapant ça je m'aperçois que le deuxième point n'est pas spécifique aux exceptions jours fériés, c'est valable avec toutes les sources (import d'un ICS -> duplication -> suppression de l'ICS dans le guichet dupliqué (rien ne se passe) -> suppression de l'ICS dans le fichier initial (exception supprimées dans les deux guichets).

#9

Updated by Valentin Deniaud about 4 years ago

Valentin Deniaud a écrit :

Et en tapant ça je m'aperçois que le deuxième point n'est pas spécifique aux exceptions jours fériés, c'est valable avec toutes les sources (import d'un ICS -> duplication -> suppression de l'ICS dans le guichet dupliqué (rien ne se passe) -> suppression de l'ICS dans le fichier initial (exception supprimées dans les deux guichets).

Mais ça s'autocorrige tout seul au bout d'une heure avec la commande qui synchronise les ICS (cycle qui supprime/remet les exceptions), c'est pour ça que c'est passé sous les radars. Pas besoin de migration qui rattrape, donc.

#10

Updated by Valentin Deniaud about 4 years ago

  • Subject changed from Source d'exception jours fériés, n'importe quoi sur la prod to Incohérences lors de la duplication d'un guichet avec des sources d'exceptions
#11

Updated by Benjamin Dauvergne about 4 years ago

0001 : ok
0002 : ok
0003 : ok, juste je me demande si prendre le premier des doublons d'une source ayant des exceptions est suffisant, par rapport à leur état (source.enabled)

Note pour moi : pour le 0003 il faut juste se mettre dans l'idée quand on lit qu'en fait les sources passent leur temps à effacer toutes les exceptions qui leur sont liées à chaque fois qu'elles se mettent à jour, donc en fait on a très peu de chance de trouver des exceptions incohérentes (lièe au mauvais bureau, j'ai eu un peu du mal à comprendre pourquoi on pouvait en faire aussi peu) et supprimer les sources en trop suffit (aucune source ne manque et il n'y a pas de doublon de source pour le type de source "ics")


On peut peut-être remplacé ça par un update_or_create() maintenant qu'on a un index d'unicité :

            try:
                source = TimePeriodExceptionSource.objects.get(desk=self, settings_slug=slug)
            except TimePeriodExceptionSource.DoesNotExist:
                source = TimePeriodExceptionSource.objects.create(
                    desk=self, settings_slug=slug, enabled=False
                )

#12

Updated by Benjamin Dauvergne about 4 years ago

  • Status changed from Solution proposée to Solution validée
#13

Updated by Valentin Deniaud about 4 years ago

Thx pour la relecture.

Benjamin Dauvergne a écrit :

0003 : ok, juste je me demande si prendre le premier des doublons d'une source ayant des exceptions est suffisant, par rapport à leur état (source.enabled)

Quand tu dupliques une première fois, tu te retrouves avec deux sources enabled, l'une créée par l'import lors du save(), l'autre par la duplication. On veut garder la première, qui a correctement créé ses exceptions, et pas la seconde. Donc on voit qu'on ne peut pas se fier à enabled pour prendre des décisions ici.
Lors des duplications suivantes, on peut se retrouver avec plusieurs sources enabled qui ont des exceptions, il suffit d'en choisir une au pif.

On peut peut-être remplacé ça par un update_or_create() maintenant qu'on a un index d'unicité :

En vrai je relis cette ligne et je ne comprends pas pourquoi il n'y a pas un get_or_create (certes il n'y a pas d'index d'unicité mais je ne pense pas que ce soit la raison vu que le même pb se pose avec get tout court). Par contre update_or_create je pense pas, on ne veut pas mettre à jour la valeur de enabled. Trop frileux pour y toucher ici en tout cas.

#14

Updated by Valentin Deniaud about 4 years ago

Valentin Deniaud a écrit :

Benjamin Dauvergne a écrit :

0003 : ok, juste je me demande si prendre le premier des doublons d'une source ayant des exceptions est suffisant, par rapport à leur état (source.enabled)

Quand tu dupliques une première fois, tu te retrouves avec deux sources enabled, l'une créée par l'import lors du save(), l'autre par la duplication. On veut garder la première, qui a correctement créé ses exceptions, et pas la seconde. Donc on voit qu'on ne peut pas se fier à enabled pour prendre des décisions ici.
Lors des duplications suivantes, on peut se retrouver avec plusieurs sources enabled qui ont des exceptions, il suffit d'en choisir une au pif.

Bon aller à la rigueur il y a un cas où on peut se permettre d'être plus intelligent :
  • duplication comme je décris, le guichet dupliqué a une source enabled avec des exceptions, l'autre enabled sans
  • quelqu'un vient désactiver la source avec des exceptions
  • la migration risque de garder la source enabled qui n'a pas d'exceptions, alors qu'on aurait voulu celle dans un état cohérent.

J'ajoute un petit if qui gère ça et je pousse.

#15

Updated by Valentin Deniaud about 4 years ago

  • Status changed from Solution validée to Résolu (à déployer)
commit c1d5eb32ee80623810c8a016d33e612bec0b1ffb
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Wed Oct 21 17:47:38 2020 +0200

    agendas: add unicity constraint on exception source slug (#47916)

commit bb3e011beaec6dddedc0a30698e03e74f8f95bb3
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Thu Oct 22 11:59:31 2020 +0200

    agendas: do not import exception from settings when duplicating (#47916)

commit f880490e00e82986733cbcf2369d6c5f7e80213f
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Thu Oct 22 11:58:55 2020 +0200

    agendas: set proper exception source when duplicating (#47916)
#16

Updated by Frédéric Péters about 4 years ago

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

Also available in: Atom PDF