ZEP-12 : refonte du principe des tutoriels et articles

Avec pour base atomique ... l'extrait

Le problème exposé dans ce sujet a été résolu.

Ok pour les .tutos. Mais pour le principe de précautions, c'est pas pour rien qu'on a un gestionnaire de sources :D

En fait, quoi qu'il arrive, on aura besoin des anciens modèles et factory pour assurer que les scripts de migration sont bons etc.

La seule chose qui peut être enlevée, ce sont les vues, les urls et leurs tests. Je ne peux pas faire mieux pour l'instant.

  1. « On doit pouvoir importer les fichiers .tuto et archives zip »: on a jamais aussi bien géré les ZIPs (on peut même importer des images avec, grâce à artragis), par contre, on a un peu laissé tomber le .tuto, et à priori, on ne le fera pas. Sauf si quelqu'un dit qu'on peut pas sortir sans ça.

TLDR : Je ne pense pas qu'il faille s'embêter à supporter l'import du .tuto dans la ZEP-12 alors que la ZEP12 sait migrer un tutoriel dans le format actuel.

Considérons les appellations suivantes :

  • format point-tuto : le format issu du SdZ de l'époque, qui est un fichier dont la structure et le contenu est purement du xml
  • format semi-point-tuto : qui correspondant au format point-tuto sur lequel le contenu n'est plus en xml, mais en markdown. Cependant la structure est toujours en xml. Un mix donc de xml et de markdown.
  • format zds-v1 : qui correspond à un tutoriel versionné dans un dépot git dont la structure est définie par un fichier json, et le contenu est un ensemble de fichiers markdown
  • format zds-v2 : le nouveau format mis en place par la zep-12, qui reprend le format zds-v1 et qui rajoute des champs dans le fichier de structure json.

pour passer du format point-tuto au format semi-point-tuto il existe un script java (un jar en somme) qui s'en occupe et qui marche très bien. Pour passer d'un semi-point-tuto au format zds-v1 il faut passer par le site (en ligne) ou par n'importe qu'elle instance de zds en local depuis la v1.0.

La zep-12 inclut un script qui permet de passer du format zds-v1 au format zds-v2. Étant donné que tous les .tuto sont déjà sur le serveur, on pourrait faire rouler la mécanique pour convertir tous les fichier .tuto au format zds-v1 (et l'attribuer a l'auteur externe par exemple) avant de MEP la zep-12.

Ainsi, plus besoin de faire supporter le format semi-point-tuto à la ZEP-12.

3.« Les urls existantes doivent rester valides (SEO toussa) » : oui … Mais non. Lorsqu'on visitera un ancien tuto/article, on sera redirigé vers sa page principale. Ça ne choque pas pour les articles/mini-tuto, c'est un peut plus choquant dans le cas des big-tutos.

Je dirais même que c'est assez bloquant pour les big-tutos. On risque de péter complètement le SEO existant avec ça. Lorsqu'on regarde notre tutoriel le mieux référencé, celui sur Symfony2, Google référence les urls des chapitres directement. Si on s'amuse à le renvoyer sur le la même page, c'est à dire le sommaire du tutoriel, on se prend des duplicate content sur toutes nos urls, la sanction sera sans appel.

Il faut trouver un moyen efficace de mapper les anciennes urls sur les nouvelles. La comme ça pour gérer ça, je ne vois que la solution d'un attribut optionnel (old_slug) dans le json qui sera sous la forme id/old-slug et qui permettra de faire les bonnes redirections.

Il faut trouver un moyen efficace de mapper les anciennes urls sur les nouvelles. La comme ça pour gérer ça, je ne vois que la solution d'un attribut optionnel (old_slug) dans le json qui sera sous la forme id/old-slug et qui permettra de faire les bonnes redirections.

faut que je vérifie, mais il me semble que dans le cas des bigs tutos qui ont des urls au format pk-tuto/slug-tuto/pk-part/slug-part/pk-chapter/slug-chapter/ on a déjà un truc qui nous renvoie à la bonne page. et qui marche pas trop mal.

J'ai vérifié et surtout j'ai débuggé le système dont je parlais : il permet de rediriger toutes les urls du type pk-tuto/slug-tuto/pk-part/slug-part/pk-chapter/slug-chapter/ vers leur nouvel équivalent sans duplicate content. Par contre les urls du type pk-tuto/slug-tuto/pk-part/slug-part/ ne sont pas redirigées pour l'instant. je vais voir ce que je peux faire, mais je ne suis sûr de rien.

Tant que les slugs de chapitres ne changent pas.

pierre_24

Quand tu dis ne change pas, tu parles d'une url d'un chapitre qui a changé "avant-mep-zep-12" ou "apres-mep-zep-12" ?

Car si c'est avant MEP, étant donné que les urls sont au format id-tuto/slug/id-part/slug/id-chap/slug, il suffit de prendre ton old-slug qui devrait correspondre à id-chap/slug pour un chapitre, et considérer non plus la valeur exacte id-chap/slug, mais le joker id-chap/*

Je ne sais pas si vous voyer ce que je veux dire.

Je parle d'un chapitre "a" qui serait modifié par la suite en "b".

En fait, ce que tu dis est tout à fait vrai, mais obligerait à modifier la structure de notre manifest pour les rajouter. Pas que ce soit impossible, que du contraire, mais c'est rajouter un champ de rétro-compatibilité qui n'aurait plus de sens dans quelques mois (ce qui "obligerait" à le déprécier), est ce que ça a du sens ? (d'autant que le cas se pose actuellement, si un chapitre change de slug, bah le SEO suis pas, point :p )

d'autant que le cas se pose actuellement, si un chapitre change de slug, bah le SEO suis pas, point :p )

dans le module v1 les urls ne sont pas sensibles au slug. c'est la pk qui fait tout.

un moyen d'y arriver serait de ne jamais changer le slug lorsqu'on change le nom du chapitre/partie.

Une question : est-il facile d'ajouter un type de contenu ? Au hasard, un type "tribune libre".

Une remarque : il ne me semble pas qu'il y ait de page indiquant à l'auteur certains détails sur le processus de rédaction/publication. Notamment, il aimera probablement savoir ce que devient son contenu s'il se désinscrit ou s'il est possible de le dépublier sur demande. La doc est un peu technique pour être consultable par tous les auteurs. Ai-je manqué quelque chose ? Peut-être vaut-il mieux mettre ça dans le guide du contributeur ?

Merci !

+0 -0

Pour les tribunes libre, cela pourra être fait, relativement facilement de ce que j'ai vu du code (ça prendra plusieurs heures de dev, mais techniquement, ça sera pas très compliqué).

Pour les contenus, les admins peuvent dépublier à la demande. C'est un clique sur une interface. Si il choisi de se désincrire, par-défaut, son profil est effacé. Le contenu qu'il à écrit apparaîtra sous le nom d'"auteur externe". Si il souhaite tout supprimer, il faut faire une demande à un admin.

Jamais personne ne refusera de dé-publier le contenu, si il fait la demande.

La doc est ici.

+1 -0

Une question : est-il facile d'ajouter un type de contenu ? Au hasard, un type "tribune libre".

Dans la théorie, oui, c'est assez simple, il suffit d'aller déclarer le type là bas et c'est parti. En pratique, c'est un tout petit peu plus complexe parce que y'a souvent des if/else impliqués dans l'histoire, par exemple pour afficher le bon mot au bon endroit. Mais rien de vraiment très complexe :)

Une remarque : il ne me semble pas qu'il y ait de page indiquant à l'auteur certains détails sur le processus de rédaction/publication. Notamment, il aimera probablement savoir ce que devient son contenu s'il se désinscrit ou s'il est possible de le dépublier sur demande. La doc est un peu technique pour être consultable par tous les auteurs. Ai-je manqué quelque chose ? Peut-être vaut-il mieux mettre ça dans le guide du contributeur ?

Le texte de désincription est très clair sur ce qu'il va arriver:

Attention xxx, vous êtes sur le point de vous désinscrire de Zeste de Savoir. Voici ce qu'implique cette action qui ne peut être annulée :

  • Toutes vos conversations privées (MP) seront perdues ;
  • Tous vos messages de forums seront anonymisés ;
  • Votre compte et tout ses détails seront supprimés, cela signifie que l'adresse courriel (xxx@gmail.com) sera effacée du système et votre pseudo (xxx) sera libéré et utilisable par un autre membre ;
  • Vos tutoriels et articles non publiés (brouillon, bêta ou en cours de validation) seront supprimés sans possibilité de récuperation (sauf si d'autres auteurs sont présents lors de la rédaction) ;
  • Vos tutoriels et articles publiés subiront les modifications suivantes :
    • si vous étiez seul, ils seront placés sous la gouvernance du compte "Auteur Externe", sauf demande contraire de votre part à un membre du staff avant votre désinscription ;
    • si vous étiez plusieurs auteurs, vous quitterez le groupe de rédacteurs. Les autres pourront dès lors continuer sans vous.

Si vous souhaitez poursuivre votre désinscription, cliquez sur le bouton Me désinscrire ci-dessous. Sinon il n'est pas encore trop tard …

Pour moi, le reste devrait faire partie du fameux "guide du contributeur" (que je pense qu'on peut penser à écrire, vu que la ZEP-12 devrait plus vraiment changer)

Merci !

Vayel

De rien, comme toujours ;)

Bonjour à tous, on touche à la fin !

Globalement la zep est stable, et plutôt bien mise en place il ne nous reste plus que la recherche.

Et devinez quoi : ça ne coince pas tant que ça grâce à Hugo \o/. Seul petit bémol à tout ça : nous avons deux solutions techniques pour la mise en place de la recherche et ni pierre ni Hugo, ni moi n'arrivons à prendre la décision sur laquelle est la bonne.

Je copie/colle les descriptions que fait Hugo de ces décisions techniques.

Solution 1 : Indexation synchrone à la publication

Lors de la publication d'un contenu, les informations sur le contenu sont enregistrés, les extraits sont stocké dans une table SearchIndexExtracts, les chapitres et parties sont stocké dans une autre table SearchIndexContainers et les informations sur le contenu sont stockés dans une table nommé SearchIndexContents, les auteurs et sous catégories sont eux aussi stockés dans deux tables. L'architecture des tables sont dans le fichiers zds/search/migrations/0001_initial.py et models.py.

À chaque publication, je supprime tous ce qui concerne le contenu qui va être publié dans les tables de recherche, et je l’insère dans les tables de la recherche. Cette algorithme génère les IO et les requêtes présentés dans l'autre messages:

  • IO complexity is 2 + (2*number of containers) + number of extracts.
  • Database query complexity is
  • on deletion 1+number of containers+number of extracts,
  • on addition 1+number of containers+number of extracts.

Cet algorithme est visible dans le fichier zds/search/utils/utils.py. Ces opérations sont lancés dans un Thread mais il y'a deux soucis principaux, si j'ai bien compris les ressources en ligne, il y'a pas vraiment de parallélisme avec les Thread. Tous les Threads sont lancés sur le même cœur du processeurs et les threads vont s’exécuter séquentiellement. C'est assez comment dire dommage pour nous. Le deuxième soucis est que la base de donnée, SQLite ne prend pas en charge la concurence des insertions et suppressions sur une table. J'ai trouvé un contournement sur StackOverflow, dans le code, c'est ici.

Cette branche comprend aussi la modification des fichiers search_indexes.py qui définissent ce qui est stockés et indexés dans Solr. Le contenu indexés est dans les fichiers searchindexcontainer_text.txt et searchindexcontent_text.txt et searchindexextract_text.txt.

Solution 2 : Indexation via une commande

Avec la commande update_content

Arguments pour

1
2
3
4
5
- L'ajout des informations dans les tables de recherche est séparé de la publication
- On pourrais toujours si on veut changer le comportement plus tard et indexer à la publication
- On peut mesurer plus précisément le temps de chargement de l'indexation
- Le code de la publication est un peu long, si on peut le raccourcir de quelques lignes …
- On évite de se faire chier avec les Thread.

Arguments contre

1
2
3
- Une commande de plus à taper à chaque fois
- Faut faire attention à ne pas lancer en même temps, la commande update_content et la commande rebuild_index de Solr. 
- Obligé de recopier le markdown dans le dossier extra_contents

Enregistrer les informations lors de la publication

Arguments pour

1
2
- Tout est au même endroit dans le code, c'est un peu plus facile de s'y retrouver pour quelqu'un qui ne connaît pas le code.
- Pas obligé de recopier le markdown dans extra_contents

Arguments contre

1
2
- Difficile de connaître le coût de l'indexation
- Le Threading en Python est très limité et on rallongera, de toute manière un peu la publication.

Comment tester ?

  • Lancer la migration avec python manage.py migrate
  • Changer le schema.xml
  • Si vous avez déja des tutoriel publé, il suffit de lancer la commande python manage.py index_content, la commande se chargera de copier le markdown publié dans le repo publique et de copier les données dans la table de recherche.
  • Lancer Solr et executer la commande python manage.py rebuild_index

Comment ça marche ?

À la publication, on flag le PublishableContent pour indiquer qu'il faut ré-indexer le contenu, on copie aussi le markdown dans le dossier extrat_content.

Quand on execute la commande python manage.py index_content, le script cherche tous les tutos avec un flag et copie les informations du contenu dans les tables de recherche dans la base de données.

Aprés, il suffit de faire python manage.py rebuild_index, pour indexés les données.

Notons que la deuxième solution a été mise en place sur mon serveur. Un léger bug a été détecté à cause de l'unicode qui sera rapidement corrigé. Cette mise en place permet d'ajouter un argument "pour" que devraient apprécier nos sysadmin : c'est ultra simple à mettre en place et à maîtriser.

Que choisir

J'ai fait ce message dans une visée de transparence et de communication technique de ce qu'on fait. Dans ce cas précis, rien n'est vraiment "vulgarisé" et je pense vraiment que c'est aux directeurs technique, systadmin et CDP de choisir, néanmoins, si vous désirez que la communauté vote, premier solution = up deuxième solution = down.

Je vais juste tenter de résumer le message, un peu plus clairement.

Le probléme

On a fait un choix, c'était de partir sur la solution de Spacefox pour l'indexation des données. La solution en résumé, était de créé des tables spéciales pour la recherche qui ne servirait que pour l'indexation. Ces tables ont été créées et elles sont ici. Ces tables sont SearchIndexContent, SearchIndexContainers, SearchIndexExtracts, SearchIndexAuthors, SearchIndexTags.

Mais ces tables doivent-être remplies, il est impossible de le faire à la publication de façon synchrone, car cette opération prend du temps et des IO. Pour rappel, c'est de cet ordre la:

  • IO: 2 + (2*numbre de conteners) + nombre d'extrait
  • Pour la base de données:
    • En suppression 1+nombre de conteners+nombre d'extraits,
    • En ajout 1+number de conteners + nombre d'extraits

Les solutions proposées

Deux solutions sont donc proposées soit de remplir les tables de la recherche à la publication de manière Asynchrone avec des Threads ou de remplir les tables plus tard avec une commande Django.

Première solution: remplir les tables à la publication avec un Thread

Lors de la publication, on lance un Thread, qui va remplir les tables de la recherches.

Les avantages sont les suivants:

  • Tout est au même endroit dans le code, c'est un peu plus facile de s'y retrouver pour quelqu'un qui ne connaît pas le code.
  • Pas obligé de recopier le markdown dans extra_contents

Les désavantages sont:

  • La base de données de test ne supporte pas les Threads.
  • SQLite prend très mal en charge la concurrence mais si une solution existe, c'est d'augmenter le timeout.
  • Difficile de connaître le coût de l'indexation
  • Si j'ai bien compris comment fonctionne l'ordonnanceur de Python, le Threading en Python est très limité (les threads tournent sur un seul coeur, séquentiellement) et on rallongera, de toute manière un peu la publication.
  • Obligé de couper le site, si on veut copier les données des tables de la recherche à la demande. Exemple, un tutoriel s'est mal indexés, et on veut recopier les données des tables de recherches.

Deuxième solution: remplir les tables avec la commande

Lors de la publication, on flag le tutoriel en indiquant qu'il doit-être ré-indexé et on copie le repository markdown dans le dossier extra_content. Pour pouvoir y avoir accès après.

Plus tard, lors du lancement de la commande Django, on recherche tous les tutoriel avec un flag, et on remplis les tables de la recherche.

Les avantages sont les suivants:

  • L'ajout des informations dans les tables de recherche est séparé de la publication
  • On pourrais toujours si on veut changer le comportement plus tard et indexer à la publication
  • On peut mesurer plus précisément le temps de chargement de l'indexation
  • Le code de la publication est un peu long, si on peut le raccourcir de quelques lignes …
  • Plus de Thread, plus de probléme.

Les inconvénients sont:

  • Une commande de plus à taper à chaque fois
  • Faut faire attention à ne pas lancer en même temps, la commande update_content et la commande rebuild_index de Solr.
  • Obligé de recopier le dépot markdown dans le dossier extra_contents

Les avantages et inconvénients reflète ma façon de pensée, et n'est pas neutre, garder ça à l'esprit.

EDIT: Vous pouvez voir comment se comporte un peu la recherche sur le serveur Artragis.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte