Différences entre les versions de « Archéo Lex/Repo Git »

De Wiki Seb35
Aller à la navigation Aller à la recherche
(Page créée avec « Cette page fait état de l’architecture du/des repos Git créés par Archéo Lex, eu égard des contraintes (performance, stockage) et des usages possibles. == Existant... »)
 
 
(2 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
Cette page fait état de l’architecture du/des repos Git créés par Archéo Lex, eu égard des contraintes (performance, stockage) et des usages possibles.
Cette page fait état de l’architecture du/des repos Git créés par Archéo Lex, eu égard des contraintes (performance, stockage) et des usages possibles.
Voir aussi [[Monorepo Git]].
NB :
* ''repo'' = repository = dépôt Git
* ''repos'' = pluriel de ''repo''


== Existant ==
== Existant ==
Ligne 31 : Ligne 37 :
Le problème de performance est en partie sur le ''fichier des références packed-refs'' lors de son écriture. Celui-ci est un fichier texte dont la 1ère colonne sont des SHA-1 (40 octets) et la 2e colonne sont les refs correspondantes (longueur variable, probablement autour de 30 octets puisque les références seraient nommées comme refs/lois/loi_2021-689/texte (28 caractères) ou refs/décrets/décret_2021-699/texte (36 caractères)) ; ce fichier est trié, la 2e colonne étant la clé (il y a donc une problématique de tri lors de l’écriture de ce fichier). Sa taille est donc environ 70 octets x (nombre de textes) = 14 Mo pour 200k décrets.
Le problème de performance est en partie sur le ''fichier des références packed-refs'' lors de son écriture. Celui-ci est un fichier texte dont la 1ère colonne sont des SHA-1 (40 octets) et la 2e colonne sont les refs correspondantes (longueur variable, probablement autour de 30 octets puisque les références seraient nommées comme refs/lois/loi_2021-689/texte (28 caractères) ou refs/décrets/décret_2021-699/texte (36 caractères)) ; ce fichier est trié, la 2e colonne étant la clé (il y a donc une problématique de tri lors de l’écriture de ce fichier). Sa taille est donc environ 70 octets x (nombre de textes) = 14 Mo pour 200k décrets.


Cela reste gérable si on ne conserve pas les versions passées des références (on a que la base LEGI+JORF du jour), mais n’est plus gérable si on veut garder les références de chaque texte des bases LEGI+JORF pour chaque jour (par ex. refs/codes/code_civil/texte/markdown/20181019-200412/vigueur), ou alors il ne faut stocker que les quelques textes mis à jour (et avoir un mécanisme pour requêter la base LEGI de n’importe quel jour en allant chercher la plus récente référence du texte avant ce jour).
Cela reste gérable en taille (mais ça commence à faire vraiment beaucoup en nombre de refs) si on ne conserve pas les versions passées des références (on a que la base LEGI+JORF du jour), mais n’est plus gérable si on veut garder les références de chaque texte des bases LEGI+JORF pour chaque jour (par ex. refs/codes/code_civil/texte/markdown/20181019-200412/vigueur), ou alors il ne faut stocker que les quelques textes mis à jour (et avoir un mécanisme pour requêter la base LEGI de n’importe quel jour en allant chercher la plus récente référence du texte avant ce jour).
 
Voir aussi [https://github.com/git/git/blob/master/Documentation/technical/reftable.txt reftable] en cours d’implémentation dans Git (2021), qui optimisera l’accès aux références : temps constant quel que soit le nombre de références au lieu du temps linéaire actuel + enregistrement incrémental au lieu de l’enregistrement global actuel. Les ordres de grandeur donnés dans la spec reftable est 31k refs pour rails et 866k refs pour android. Le stockage des reflogs est géré également selon le même mécanisme.


==== Protocole ''smart'' de Git ====
==== Protocole ''smart'' de Git ====


Lors d’un essai sur un gros repo git avec de nombreuses références, j’ai expérimenté un échange interminable où le client dit qu’il a telle et telle référence (have xxxx [https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols]) (c’était il y a 1 ou 2 ans, je crois qu’il y a un nouveau mécanisme pour optimiser cette étape).
Lors d’un essai sur un gros repo git avec de nombreuses références, j’ai expérimenté un échange interminable où le client dit qu’il a telle et telle référence (have xxxx [https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols]) (c’était il y a 1 ou 2 ans, je crois qu’il y a un nouveau mécanisme pour optimiser cette étape).
== Future architecture ==
=== v2 ===
1) Conserver les '''3 organisations actuelles des fichiers''' ("texte", "sections", "articles"), cela est éprouvé même si on peut améliorer à la marge (par exemple : noms des fichiers lorsque ça dépasse 255 caractères en ajoutant un sommaire, etc.). Sur la publication sur archeo-lex.fr, je pense publier uniquement l’organisation "texte" qui ne souffre pas de limitations sur le nommage des articles et est plus éprouvée jusqu’à présent.
2) Conserver les '''2 noms de branches relatifs à la vigueur du texte''' ("texte" et "texte-futur", etc pour les autres organisations des fichiers), cela est éprouvé et permet de savoir quasi-immédiatement le statut de vigueur du texte (la seule ambiguité est si le texte est abrogé : il y a une branche "texte" ne contenant aucun fichier).
3) '''Utiliser les reflogs pour stocker l’historique du repo''' -- confirmer que ça serait suffisamment adapté, notamment :
# pour retrouver l’état d’une ref à une date passée,
# pour fixer la date de changement de la ref (fixer au jour d’entrée en vigueur minuit même si on exécute la commande à 22:50:25 la veille),
# optionnellement pour créer des packfiles "historiques" contenant les très anciennes versions des références
4) Continuer à '''servir publiquement des repos "codes/code_civil.git" et y ajouter "lois/loi_2021-689.git" et "décrets/décret_2021-699.git"''' : cela est utile pour SedLex quand on veut consolider un texte (par ex. un amendement qui modifie la version en vigueur du code civil). L’implémentation côté serveur reste à déterminer.
5) Servir '''publiquement des repos "lois.git" et "décrets.git"''' contenant des sous-modules par année "lois/2020.git", "décrets/2020.git", liant vers les repos autonomes ci-dessus (pour le repo "codes.git" : directement les respos autonomes). Les mises à jour de ces repos seraient relativement rapides : seuls les sous-modules par année modifiée seraient mis à jour, et il y a actuellement dans LEGI 50 lois/an, 1500 décrets/an, 3000 arrêtés/an. Possiblement, dans une version intégrée, les sous-modules par année pourraient être des branches du repo parent afin de tout télécharger en même temps (et non télécharger à N+1 repos) ; j’ai testé récemment avec Git 2.30, c’est possible avec une URL de sous-module de la forme "./" (et il faut que l’objet commit du sous-module soit dans le repo courant, d’où la nécessité que ce soit dans une branche ou un tag).
La granularité "année" peut être changée en "mois" voire "jour" pour mettre par exemple les décrets datés du 21 juin 2020 dans le repo "décrets/2020/06/21.git" (noter que, vu le processus de consolidation, les sous-modules évolueront quelque soit la granularité vis-à-vis de leur date de publication). Plus la granularité est forte, moins chaque sous-module sera mis à jour (mais plus le téléchargement initial mettra de temps puisqu’il faudra télécharger plus de repos distincts). Un panachage du stockage peut être introduit : par exemple stockage des sous-modules par année dans le repo principal, puis téléchargement distant des sous-modules par mois.
Une version plus évoluée pourrait être que, pour une granularité "mois", les 3 derniers mois sont stockés dans des branches (donc téléchargés d’office initialement) et les plus anciens sont téléchargeables au cas par cas ; dans cette configuration, cela demande côté client de changer la configuration ".git/config" puisque les branches du mois vont disparaître du repo principal avec le temps et il faudra alors les télécharger explicitement.
Côté serveur, il serait possible d’utiliser les "gitnamespaces" [https://git-scm.com/docs/gitnamespaces] avec une certaine configuration nginx pour stocker efficacement ces repos dans un seul repo (ou 2 ou 3 par granularité, à tester vis-à-vis de la performance), et la performance devrait rester acceptable au moins jusqu’à une granularité du mois (250 ans x 12 mois + 250 sommaires = 3250 refs).

Version actuelle datée du 10 août 2021 à 18:34

Cette page fait état de l’architecture du/des repos Git créés par Archéo Lex, eu égard des contraintes (performance, stockage) et des usages possibles.

Voir aussi Monorepo Git.

NB :

  • repo = repository = dépôt Git
  • repos = pluriel de repo

Existant

État des lieux

Actuellement, Archéo Lex crée un repo par texte et a trois variantes de repo (paramètre --organisation) :

  • la principale est de placer tous le texte en Markdown dans un seul fichier texte ;
  • la seconde est de placer le contenu des articles dans des fichiers autonomes, à plat dans le dossier principal ;
  • la troisième est de créer des sous-dossiers par section/sous-section du texte et de placer le contenu des articles dans des fichiers dans cette arborescence.

Il y a 1 ou 2 références par texte :

  • "texte" (ou "sections" ou "articles") : le texte en vigueur
  • "texte-futur" (ou "sections-futur" ou "articles-futur") : le texte en vigueur future (=prévu à une date future, par exemple au 1er janvier de l’année prochaine)

Problèmes

Ordre de grandeur

Cette organisation est adaptée pour les codes étant donné leur faible nombre (≈108 dont ≈74 en vigueur) : il n’y a que 1 ou 2 références par repo, ce qui ne pose pas de problèmes de performances.

Il est possible de créer un repo "codes" comprenant tous les codes (ou tous les codes en vigueur selon ce qu’on veut exposer), ce qui ne fait que ≈200 références. Toutefois, si on cherche (et c’est le cas) à généraliser Archéo Lex aux lois (≈12600[problemes-sur-l-existant 1] dont entre 2,7k et 12k en vigueur[problemes-sur-l-existant 2]), il peut y avoir des problèmes de performances d’autant plus qu’on ajoute les décrets (50k décrets dans LEGI, 200k dans JORF[problemes-sur-l-existant 3]) ou les arrêtés (70k dans LEGI, 600k dans JORF[problemes-sur-l-existant 4]).

Notes

  1. 12595 avec nature='LOI' dans la base JORF au 9 février 2019 via cette PR
  2. Au 9 août 2021 dans la base LEGI : 2746 lois en vigueur, 500 abrogrés, peu avec des statuts autres, total de 3331 lois ; il manque donc au moins ≈7000 lois dans la base LEGI dont on ne connait pas le statut abrogation ou vigueur
  3. Au 9 août 2021 dans la base LEGI : 49129 décrets dont 38287 en vigueur, 8066 abrogés, 1238 périmés, quelques dizaines pour les autres statuts. Au 9 février 2019 dans la base JORF : 204051 décrets.
  4. Au 9 août 2021 dans la base LEGI : 69812 arrêtés dont 53051 en vigueur, 12328 abrogés, 2306 périmés, quelques dizaines ou centaines dans les autres statuts. Au 9 février 2019 dans la base JORF : 606909 arrêtés.

Fichier des références packed-refs

Le problème de performance est en partie sur le fichier des références packed-refs lors de son écriture. Celui-ci est un fichier texte dont la 1ère colonne sont des SHA-1 (40 octets) et la 2e colonne sont les refs correspondantes (longueur variable, probablement autour de 30 octets puisque les références seraient nommées comme refs/lois/loi_2021-689/texte (28 caractères) ou refs/décrets/décret_2021-699/texte (36 caractères)) ; ce fichier est trié, la 2e colonne étant la clé (il y a donc une problématique de tri lors de l’écriture de ce fichier). Sa taille est donc environ 70 octets x (nombre de textes) = 14 Mo pour 200k décrets.

Cela reste gérable en taille (mais ça commence à faire vraiment beaucoup en nombre de refs) si on ne conserve pas les versions passées des références (on a que la base LEGI+JORF du jour), mais n’est plus gérable si on veut garder les références de chaque texte des bases LEGI+JORF pour chaque jour (par ex. refs/codes/code_civil/texte/markdown/20181019-200412/vigueur), ou alors il ne faut stocker que les quelques textes mis à jour (et avoir un mécanisme pour requêter la base LEGI de n’importe quel jour en allant chercher la plus récente référence du texte avant ce jour).

Voir aussi reftable en cours d’implémentation dans Git (2021), qui optimisera l’accès aux références : temps constant quel que soit le nombre de références au lieu du temps linéaire actuel + enregistrement incrémental au lieu de l’enregistrement global actuel. Les ordres de grandeur donnés dans la spec reftable est 31k refs pour rails et 866k refs pour android. Le stockage des reflogs est géré également selon le même mécanisme.

Protocole smart de Git

Lors d’un essai sur un gros repo git avec de nombreuses références, j’ai expérimenté un échange interminable où le client dit qu’il a telle et telle référence (have xxxx [1]) (c’était il y a 1 ou 2 ans, je crois qu’il y a un nouveau mécanisme pour optimiser cette étape).

Future architecture

v2

1) Conserver les 3 organisations actuelles des fichiers ("texte", "sections", "articles"), cela est éprouvé même si on peut améliorer à la marge (par exemple : noms des fichiers lorsque ça dépasse 255 caractères en ajoutant un sommaire, etc.). Sur la publication sur archeo-lex.fr, je pense publier uniquement l’organisation "texte" qui ne souffre pas de limitations sur le nommage des articles et est plus éprouvée jusqu’à présent.


2) Conserver les 2 noms de branches relatifs à la vigueur du texte ("texte" et "texte-futur", etc pour les autres organisations des fichiers), cela est éprouvé et permet de savoir quasi-immédiatement le statut de vigueur du texte (la seule ambiguité est si le texte est abrogé : il y a une branche "texte" ne contenant aucun fichier).


3) Utiliser les reflogs pour stocker l’historique du repo -- confirmer que ça serait suffisamment adapté, notamment :

  1. pour retrouver l’état d’une ref à une date passée,
  2. pour fixer la date de changement de la ref (fixer au jour d’entrée en vigueur minuit même si on exécute la commande à 22:50:25 la veille),
  3. optionnellement pour créer des packfiles "historiques" contenant les très anciennes versions des références


4) Continuer à servir publiquement des repos "codes/code_civil.git" et y ajouter "lois/loi_2021-689.git" et "décrets/décret_2021-699.git" : cela est utile pour SedLex quand on veut consolider un texte (par ex. un amendement qui modifie la version en vigueur du code civil). L’implémentation côté serveur reste à déterminer.


5) Servir publiquement des repos "lois.git" et "décrets.git" contenant des sous-modules par année "lois/2020.git", "décrets/2020.git", liant vers les repos autonomes ci-dessus (pour le repo "codes.git" : directement les respos autonomes). Les mises à jour de ces repos seraient relativement rapides : seuls les sous-modules par année modifiée seraient mis à jour, et il y a actuellement dans LEGI 50 lois/an, 1500 décrets/an, 3000 arrêtés/an. Possiblement, dans une version intégrée, les sous-modules par année pourraient être des branches du repo parent afin de tout télécharger en même temps (et non télécharger à N+1 repos) ; j’ai testé récemment avec Git 2.30, c’est possible avec une URL de sous-module de la forme "./" (et il faut que l’objet commit du sous-module soit dans le repo courant, d’où la nécessité que ce soit dans une branche ou un tag).

La granularité "année" peut être changée en "mois" voire "jour" pour mettre par exemple les décrets datés du 21 juin 2020 dans le repo "décrets/2020/06/21.git" (noter que, vu le processus de consolidation, les sous-modules évolueront quelque soit la granularité vis-à-vis de leur date de publication). Plus la granularité est forte, moins chaque sous-module sera mis à jour (mais plus le téléchargement initial mettra de temps puisqu’il faudra télécharger plus de repos distincts). Un panachage du stockage peut être introduit : par exemple stockage des sous-modules par année dans le repo principal, puis téléchargement distant des sous-modules par mois.

Une version plus évoluée pourrait être que, pour une granularité "mois", les 3 derniers mois sont stockés dans des branches (donc téléchargés d’office initialement) et les plus anciens sont téléchargeables au cas par cas ; dans cette configuration, cela demande côté client de changer la configuration ".git/config" puisque les branches du mois vont disparaître du repo principal avec le temps et il faudra alors les télécharger explicitement.

Côté serveur, il serait possible d’utiliser les "gitnamespaces" [2] avec une certaine configuration nginx pour stocker efficacement ces repos dans un seul repo (ou 2 ou 3 par granularité, à tester vis-à-vis de la performance), et la performance devrait rester acceptable au moins jusqu’à une granularité du mois (250 ans x 12 mois + 250 sommaires = 3250 refs).