Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatisation et calcul transparent #29

Open
fenollp opened this issue Feb 20, 2017 · 19 comments
Open

Automatisation et calcul transparent #29

fenollp opened this issue Feb 20, 2017 · 19 comments

Comments

@fenollp
Copy link

fenollp commented Feb 20, 2017

Histoire que

  • les donnees soient a jour avec LEGI
  • le calcul de ces donnees soit reproduisible par n'importe qui
  • on ait a avoir a faire confiance a moins de personnes pour s'assurer que le traitement des donnees soit bien celui que le code est sense faire (i.e. pas de moderateur/censure)

Je propose qu'on mette en place une tache cron, ou un outil de Continuous Integration (integration continue).
Il en existe beaucoup de gratuits pour les projets open source.

@Changaco
Copy link
Member

Les systèmes de CI sont conçus pour repartir de zéro à chaque commit, ils ne sont pas très adaptés à la mise à jour d'une base de données.

@fenollp
Copy link
Author

fenollp commented Feb 20, 2017

Je n'ai pas mis le nez dans le code, mais a vu de pif on telecharge la derniere tarball de ftp://ftp2.journal-officiel.gouv.fr/ et on genere un nouveau fichier markdown qu'on push ensuite ?

Si c'est le cas c'est tout a fait faisable avec les outils existant.
On ne peut pas rejeter les 3 points que j'ai mentiones plus haut uniquement avec "pas tres adapte".

@Changaco
Copy link
Member

Mettre à jour automatiquement une BDD nécessite un stockage persistant, sinon ce n'est pas une mise à jour mais une coûteuse recréation permanente.

@Seb35
Copy link
Member

Seb35 commented Feb 20, 2017

Je ne connais que peu les outils de CI, et il avait aussi été question avec Légilibre d’avoir un serveur sur lequel on ferait tourner les outils. Dans tous les cas, Archéo Lex est un peu lourd à faire tourner. Les contraintes sont actuellement :

  • avoir au minimum 15 Gio de disque,
  • par code (il y en a 73 de tailles très variables), cela prend entre 40 minutes et 10h sur mon i3 + 4Gio de RAM (le code pénal (146 versions) a mis 20 min pour mise en base de données + 40-50 min export Git ; sur le code du travail qui est en train de tourner, j’en suis à 3h (dont 1h50 de temps CPU), et vu que j’ai fait les années 1973 à 1979 (120 versions), ben c’est pas fini).

Ma machine n’est pas hyper puissante, mais il faudrait de toutes manières améliorer la parallélisation du code. Ce qui prend du temps est surtout la création des historiques Git, et c’est surtout du temps processeur, il n’y a pas besoin outre mesure de RAM. Pour paralléliser, il serait simple dans un premier temps de paralléliser sur des codes différents (indépendants). En interne d’un code, il faudrait plutôt créer des caches par sections du sommaire pour ne calculer que les sections modifiées.

Sur des outils de CI/build, je ne suis pas sûr de bien comprendre comment l’utiliser dans ce cas, la remarque de @Changaco me semble avoir du sens : il y a 73 codes à calculer, refaire tout le process de téléchargement, extraction du tarball, mise en BDD, export Git est du temps perdu pour rien ; après il est possible de calculer plusieurs codes d’un coup, mais s’il s’agit de jouer à sélectionner les codes en fonction des timeouts ça ne va pas être très drôle. Tu as quelle idée de scénario en tête ?

@fenollp
Copy link
Author

fenollp commented Feb 20, 2017

Alors si vous ne connaissez pas trop le CI voici l'idee (et mettez vous-y, c'est gratuit ! Le concept = lancer un script pour chaque push recu).

  • Separer le travail (qui m'a tout l'air d'etre embarrassingly parallel) avec une build matrix ou similaire. Ainsi avec une matrix de taille N, un push engendre N lancements du script (un "build"), chacun avec ses parametres propres.
  • Chaque build va aller chercher les data dont il a besoin, genere son markdown, clone le repo git de destination et push son markdown la bas.

Les build peuvent etre declenches par un simple POST (ou un truc a la cron deja fait pour).
Tout le monde peut lire le code, les logs du build et donc verifier que rien de malfaisant n'a ete commis.
Tout cela pour zero euros par mois.

@Seb35
Copy link
Member

Seb35 commented Feb 20, 2017

Ok, par contre étant donné la structure lourde actuelle de Archéo Lex (cf les contraintes ci-dessus), je vois pas trop comment mettre ça en place. Tu confirmes qu’on peut bien pusher un résultat vers l’extérieur de la plateforme de CI ?
Sinon la partie "clone le repo git de destination et push son markdown", ça serait bien mais ça n’est pas encore implémenté. Pour l’instant, il n’est pas possible de "compléter" un historique Git, il faut toujours le refaire ex nihilo à chaque fois. Ça serait à implémenter mais ça n’est pas aussi simple que ça en a l’air car il faut rechercher à partir de quelle date dans le passé il faut refaire l’historique, cf #28 (comment).

@Changaco
Copy link
Member

@fenollp C'est vrai que c'est une belle idée, mais elle n'est pas très efficace. Quand la machine qui met à jour les données n'est pas proche du disque dur qui contient la BDD il faut transférer plusieurs gigaoctets de données à travers l'Internet, ce qui ralentit le processus et encombre les tuyaux.

Le fait que le CI soit "gratuit" ne signifie pas qu'on peut se permettre de faire n'importe quoi avec (au contraire même, si on veut que ça reste gratuit il ne faut pas en abuser).

Ceci dit ça pourrait être intéressant d'essayer avec legi.py pour voir si ça fonctionne et combien de temps ça prend.

En ce qui concerne l'aspect confiance, même si le CI permet en effet une bonne transparence et sécurité par défaut, ça reste quand même la machine de quelqu'un d'autre (et probablement hébergée hors de France). Le seul vrai moyen de vérifier que "rien de malfaisant n'a été commis" c'est d'exécuter le programme sur une machine que tu contrôles et de comparer le résultat.

En pratique la protection la plus efficace contre l'altération des données est que celle-ci n'a aucun intérêt (en tout cas moi je n'en vois pas). Quand il n'y a pas de gain potentiel il y a peu de malfaiteurs.

@Seb35
Copy link
Member

Seb35 commented Jan 29, 2018

Je fermerai cette issue dans un mois (*) étant donné qu’elle est résolue dans un contexte légèrement différent de la proposition originale : en combinant https://github.com/Legilibre/deploiement (avec un provisionning spécifiquement pour Gandi, j’accepte les PR pour d’autres fournisseurs de VMs) et la récente amélioration d’Archéo Lex qui peut désormais mettre à jour les dépôts Git, il est désormais possible de déployer Archéo Lex littéralement en un script (après un git-clone du dépôt deploiement), la suite dépend de ce qu’on veut (one shot sur qq textes, livraison régulière de qq textes, livraison régulière de tout le corpus législatif français, etc.).

(*) @fenollp: si tu veux proposer un déploiement spécifiquement sur des outils de CI, Archéo Lex a désormais la possibilité de calculer les textes d’une liste donnée 07ea750, le reste est affaire de scripts de déploiement (setup legi.py + Archéo Lex, download, BDD, calcul AL, git-push des résultats, cron si on veut). Je te laisse proposer des PR soit sur le dépôt https://github.com/Legilibre/deploiement (il peut y avoir des languages alternatifs à Bourne shell) ou faire un autre dépôt spécifiquement de déploiement, et je ferai un lien de Archéo Lex vers ces dépôts de déploiement.

@JMLX42
Copy link
Member

JMLX42 commented Jan 29, 2018

+1 pour un CRON via Travis-CI et les dépôts sur GitHub dans une organisation dédiée

Update : au temps pour moi, la CI n'est pas forcément une bonne idée.

@JMLX42
Copy link
Member

JMLX42 commented Jan 29, 2018

Le Bureau Ouvert a envie de bosser sur ce sujet. Du coup on a créé : https://github.com/Legifrance-Git pour stocker les dépôts des textes.

Maintenant il faudrait avancer sur un orchestrateur (un simple CRON). Des idées ?

@fenollp
Copy link
Author

fenollp commented Jan 29, 2018

Je viens de push Legilibre/deploiement@master...fenollp:ci-able
L'idee est de pouvoir build sur n'importe quelle archi facilement.
Ca serait bien que le script depende de sha ou de tags mais je vois que les 2 projets n'ont pas cut de tag depuis longtemps. Aussi leurs requirements.txt ne specifient pas les numeros de version utilises.
Long story short:

+ python -m legi.download /app/tarballs
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/app/legi.py.git/legi/download.py", line 22, in <module>
    download_legi(args.directory)
  File "/app/legi.py.git/legi/download.py", line 14, in download_legi
    'ftp://legi:open1234@ftp2.journal-officiel.gouv.fr/*legi_*'
  File "/usr/lib/python2.7/subprocess.py", line 181, in check_call
    retcode = call(*popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 168, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 390, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1024, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

Il manque une dependence vers un client FTP on dirait ?

@Seb35
Copy link
Member

Seb35 commented Jan 29, 2018

@fenollp Ça a l’air pas mal ton commit. Pour l’erreur il manque peut-être wget. Pour les versions des requirements.txt, mon déploiement récent donne les versions suivantes (pip list) :

BeautifulSoup (3.2.1)
beautifulsoup4 (4.6.0)
docopt (0.6.2)
html2text (2018.1.9)
legi (0.2)
libarchive-c (2.7)
lxml (4.1.1)
path.py (10.5)
peewee (2.10.2)
pip (9.0.1)
pytz (2017.3)
setuptools (33.1.1)
tqdm (4.19.5)
wheel (0.29.0)

N’hésites pas à faire des PR s’il faut mieux préciser les versions.

@fenollp
Copy link
Author

fenollp commented Jan 29, 2018

Est-ce que tu peux push un pip freeze >requirements.txt des deux projets sur master ou une nouvelle branche ? En attendant je vais voir si ajouter wget aide.

@Seb35
Copy link
Member

Seb35 commented Jan 29, 2018

Fait pour Archéo Lex. Pour legi.py, il faut contacter @Changaco sur ledit projet.

@fenollp
Copy link
Author

fenollp commented Jan 29, 2018

Thanks! Il manquait bien wget. Maintenant il faut que je regle un probleme d'encoding des sources de legi.py je crois (ce fichier bizarrement):

connected 0 rows of textes_versions based on (nature, num)
inserted 46099 rows in textes based on (nature, num)
connected 47323 rows of textes_versions based on (nature, num)
connected 1 rows of textes_versions based on nor
connected 0 rows of textes_versions based on titrefull_s
inserted 52366 rows in textes based on nor
connected 52612 rows of textes_versions based on nor
factorized 605 duplicates into 205 uniques based on titrefull_s
connected 0 rows of textes_versions based on titrefull_s
inserted 7822 rows in textes based on titrefull_s
connected 7974 rows of textes_versions based on titrefull_s
factorized 2279 duplicates into 1085 uniques based on cid
deleted 2838 unused rows from textes
done
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/app/legi.py.git/legi/tar2sqlite.py", line 515, in <module>
    main()
  File "/app/legi.py.git/legi/tar2sqlite.py", line 510, in main
    factorize(db)
  File "legi/factorize.py", line 235, in main
    print("Il y a désormais %i textes dans la base." % n)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8: ordinal not in range(128)

J'ai l'impression que le processing des tar + l'ajout dans la DB devrait pouvoir se faire de maniere concurrente, voire creer plusieurs DB pour les merger a la fin. Peut-etre que d'avoir le fichier sqlite en memoire plutot que sur disque aiderait pas mal deja. C'est tres lent pour juste 2GB de tarballs.

@Changaco
Copy link
Member

Je ne suis pas sûr que bloquer les versions des dépendances de legi.py soit une bonne idée, ça peut vite mener à des conflits. C'est le projet à la racine de l'arbre des dépendances qui doit fixer les versions (ou pas), or legi.py peut être une dépendance d'un autre projet donc il n'est pas toujours la racine.

@Changaco
Copy link
Member

Peut-etre que d'avoir le fichier sqlite en memoire plutot que sur disque aiderait pas mal deja.

Le fichier est en mémoire, via le cache du système de fichier maintenu par le noyau (Linux). Il est possible de demander à SQLite de garder le fichier en cache côté userspace mais ça n'accélère pas vraiment le travail (cf. Legilibre/legi.py#21).

@hashar
Copy link

hashar commented Feb 17, 2018

Pour SQLite, tentez avec:

Désactiver les synchrone sur le disque:

PRAGMA synchronous OFF;

Désactiver le journal des transactions (qui permet de faire des rollbacks):

PRAGMA journal_mode OFF;

Ca devrait bien améliorer les choses, toutefois si il y a un problème (perte de courant) la base sera certainement corrompue.

@Changaco
Copy link
Member

Changaco commented Feb 17, 2018

Désactiver le journal et la synchronisation est dangereux et n'a pas d'effet sur la première conversion puisque la base de données est vide au début et que l'opération est une seule gigantesque transaction donc il n'y a rien à copier dans le journal et rien à synchroniser.

En revanche il est possible que la conversion des archives incrémentales bénéficie de journal_mode = wal et synchronous = normal. Augmenter cache_size un peu au delà des 2Mio par défaut peut aussi être bénéfique en réduisant le nombre des changements de contexte (user spacekernel space).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants