Plugin causant des erreurs lors de la reconstruction

Aujourd’hui, j’ai essayé de mettre à niveau mon installation Discourse, de la version 2.9.0.beta9 à la 2.9.0.beta10. Mais cela s’est très mal passé.

  1. Ma première tentative s’est faite sur la console
cd /var/discourse
sudo git pull
sudo ./launcher rebuild app

Celle-ci a finalement échoué, avec le message suivant quelque part au milieu de tous les logs

PG::InvalidParameterValue: ERROR:  cannot extract elements from a scalar
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:110:in `exec'

J’ai pu simplement restaurer le forum en démarrant l’ancienne image (qui traînait encore).

  1. Ma deuxième tentative s’est faite via la console web (/admin/upgrade). Mais celle-ci a finalement étouffé sur le même type d’erreur : ERROR: cannot extract elements from a scalar. En revenant au panneau de mise à niveau, il m’a indiqué que tous les composants avaient été mis à jour correctement. Mais après un redémarrage du conteneur, le serveur a maintenant lancé une erreur HTTP 500 :frowning_face:

  2. J’ai fait une nouvelle installation sur une machine séparée, en partant de zéro. J’ai pu installer la version beta10, mais essayer de restaurer à partir d’une sauvegarde a provoqué exactement la même erreur !

Quelqu’un pourrait-il m’aider ?

J’ai trouvé la requête qui pose problème

INSERT INTO question_answer_votes (post_id, user_id, created_at)

	SELECT
	  X.post_id AS post_id,
	  (X.value->>'user_id')::int AS user_id,
	  (X.value->>'created_at')::timestamp AS created_at
	FROM (
	  SELECT
	    post_id,
	    jsonb_array_elements(value::jsonb) AS value
	  FROM post_custom_fields WHERE name = 'vote_history'
	) AS X
	WHERE (X.value->>'action') != 'destroy'
	ORDER BY (X.value->>'created_at')::timestamp DESC
	ON CONFLICT DO NOTHING

Si j’ai bien compris, cela se produit parce que la fonction psql jsonb_array_elements attend un tableau, mais reçoit une valeur NULL.

Il y a eu quelques signalements à ce sujet :

Je pense que cela pourrait être lié à l’installation précédente du plugin Pavilion Question/Answer ?

Je vais voir si je peux trouver quelqu’un pour examiner cela de plus près. :+1:

Nous utilisons ce plugin : https://github.com/angusmcleod/discourse-question-answer.

  • Il semble être lié au plugin Pavilion Question and Answer.
  • C’est un fork du plugin discourse/discourse-upvotes.
1 « J'aime »

Pour vérifier, quels plugins avez-vous dans votre app.yml ?

1 « J'aime »

Le site que j’ai vu contenait un tas de ces champs personnalisés de publication qui contenaient un tas de chaînes encodées plusieurs fois, les rendant inutilisables.

Quelques solutions, par ordre de complexité :

  • arrêter d’utiliser le plugin (et peut-être passer aux nouveaux votes positifs)
  • tout supprimer
  • supprimer ceux qui sont mauvais
  • modifier ces champs pour que les données redeviennent des chaînes JSON valides.

Le site que j’ai vu contenait des données erronées datant de plusieurs années. Il semble s’agir d’un bug qui existait il y a des années et qui n’est découvert que maintenant.

Il serait peut-être possible d’écrire du code pour corriger les chaînes JSON cassées, mais je n’ai pas pu voir comment faire cela en 10 minutes.

Voir Question Answer Plugin - #301 by pfaffman pour des exemples

2 « J'aime »

J’y avais pensé aussi, mais après une rapide vérification avec la version d’Angus, il ne semble pas y avoir eu de migrations de données. https://github.com/angusmcleod/discourse-question-answer/compare/main...discourse:discourse-upvotes:main

Cela ressemble à une contamination de données provenant d’anciens messages Q&R, comme vous l’avez dit. Je trouve aussi amusant que cela apparaisse maintenant, étant donné que cette migration date de novembre 2021 - je suppose que c’est parce que JayJay ne passe que maintenant au nouveau plugin ? Quoi qu’il en soit, nous allons revoir cette migration.

1 « J'aime »
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/unfoldingWord-dev/discourse-mermaid.git
          - git clone https://github.com/angusmcleod/discourse-question-answer.git
          - git clone https://github.com/discourse/discourse-checklist.git
          - git clone https://github.com/discourse/discourse-cakeday.git
          - git clone https://github.com/discourse/discourse-canned-replies.git
          - git clone https://github.com/discourse/discourse-footnote.git
          - git clone https://github.com/discourse/discourse-staff-notes.git
          - git clone https://github.com/discourse/discourse-graphviz.git
          - git clone https://github.com/discourse/discourse-assign.git
          - git clone https://github.com/discourse/discourse-voting.git
          - git clone https://github.com/discourse/discourse-yearly-review.git
          - git clone https://github.com/discourse/discourse-saved-searches.git

1 « J'aime »

@nat Je ne passerai pas du tout au nouveau plugin. Je continue d’utiliser l’ensemble de plugins que nous avons depuis un certain temps.

Au moins une fois par mois, nous effectuons nos mises à jour, donc ce n’est pas comme s’il y avait un énorme écart entre les versions.

2 « J'aime »

Juste pour information, en dehors du problème de questions-réponses, il y a aussi un remplacement pour les réponses préenregistrées maintenant :

Et je crois qu’il existe également un composant de thème official Mermaid maintenant :

1 « J'aime »

Merci. Je regarderai cela une fois mon problème d’origine résolu :smile:

1 « J'aime »

Si je supprimais le plugin, la restauration de la sauvegarde exécuterait toujours la requête problématique.
Je devrais donc supprimer à la fois le plugin et toute table + requête utilisée par ce plugin.
Comment saurais-je quelles tables sont concernées ?

Avez-vous mis en commentaire la ligne du plugin et tenté une reconstruction pour confirmer ?

2 « J'aime »

Je vais essayer ça maintenant. J’ai parcouru le fichier dump.sql, qui fait partie de la sauvegarde, et il n’y a aucune mention d’une table question_answer_* du tout. Cela me donne donc de l’espoir…

1 « J'aime »

J’ai eu du succès sur mon système de test !

  • Désactivation du plugin
  • sudo ./launcher rebuild app
  • Restauration de la sauvegarde

Je vais travailler sur mon système en production. Je vous tiendrai au courant.

1 « J'aime »

Les données corrompues se trouvent dans la table PostCustmField. Mais si vous n’avez pas le plugin, il n’essaiera pas de migrer ces données vers la nouvelle table.

Le problème n’est pas la migration elle-même, c’est qu’à un moment donné dans le passé, les données ont été corrompues. Elles étaient cassées, mais d’une manière qui est passée inaperçue pendant des années. Je pense que chaque nouveau vote positif a pu aggraver la corruption. Une solution raisonnable pourrait être d’ignorer les données corrompues, peut-être en les marquant comme corrompues (en renommant le champ personnalisé) afin que les futures migrations puissent les ignorer et que quelqu’un puisse les corriger manuellement s’il le souhaite.

2 « J'aime »

Succès en production également. J’ai désactivé le plugin, et nous sommes repartis.
Je me demande encore pourquoi je n’ai pas rencontré ce problème plus tôt. Comme je l’ai dit, chaque mois, par routine, nous mettons à jour tous nos systèmes, donc j’aurais dû voir ce problème plus tôt.

Comment pourrais-je me connecter moi-même à la base de données Discourse, pour vérifier ce qu’il y a dans la table post_custom_fields ?

@Jaap-Jan_Swijnenburg Je suis désolé que vous ayez rencontré un problème.

Je vais respectueusement ne pas être d’accord avec vous sur ce point :slight_smile:

L’ancien plugin QnA utilisait le type de champ personnalisé standard de Discourse pour le transtypage, qui est censé gérer le transtypage de ce champ en JSON. Mais cela ne fonctionne tout simplement pas dans certains cas (comme celui-ci), c’est pourquoi vous devez (idéalement) intégrer des vérifications de format lorsque vous travaillez avec des champs personnalisés Discourse (en particulier si vous travaillez avec du code et des données assez anciens comme ceux-ci). Je suggérerais que c’est ce que le plugin Upvotes doit faire ici, d’où provient effectivement l’erreur immédiate.

Vous pouvez utiliser le plugin Data Explorer pour vérifier ce que vous avez là-bas.

Eh bien, je m’en remets principalement à vous sur ce sujet, et je pense que nous sommes d’accord. Je pense qu’il est vrai que la migration fonctionne si les données ne sont pas corrompues. Nous sommes d’accord que si les données sont corrompues, cela devrait échouer plus gracieusement que ce n’est le cas actuellement.

Oui, mais les données ont probablement été corrompues il y a des années (c’est le cas sur le site que je connais), mais vous ne l’avez pas remarqué car cela n’a pas échoué de manière catastrophique. Je suis à peu près sûr que cela ne gérait pas les votes comme prévu, mais personne ne l’a remarqué.

Je le ferais depuis rails, quelque chose comme ceci :

./launcher enter app
rails c

Ensuite, des choses comme ceci :

all_votes=PostCustomField.where(name: "vote_history")
likely_broken_votes=PostCustomField.where(name: "vote_history").where("value like '\\\"%'")

Regardez juste l’id et la valeur :

all_votes.pluck(:id,:value)

Obtenez un seul pcf :

pcf=PostCustomField.find(1234)

Corrigez-le

pcf.value='the stuff you really want in it'
pcf.save

Ce qui se passe ici, c’est ceci :

  1. Certaines personnes ont une très vieille version du plugin question-réponse avec mon nom d’utilisateur GitHub personnel dans l’URL du dépôt dans leur fichier app.yml.

  2. J’ai transféré le plugin QnA à paviliondev il y a des années. Github redirige les URL de dépôts lorsqu’ils sont transférés, donc les anciennes URL avec mon nom d’utilisateur personnel ont continué à fonctionner.

  3. Des années plus tard, Pavilion a transféré le plugin Question-Réponse à Discourse. Discourse a initialement conservé le nom discourse-question-answer.

  4. Il y a quelques mois, j’ai créé ma propre fork du plugin hébergée dans discourse, alors qu’elle s’appelait encore discourse-question-answer.

  5. Les personnes ayant de très vieux liens vers le plugin QnA avec mon compte GitHub personnel en eux clonaient désormais ma nouvelle fork du discourse-question-answer considérablement mis à jour, hébergé dans discourse. En d’autres termes, un lien très ancien pointait désormais vers une fork d’un nouveau plugin. Malgré les années écoulées, j’aurais dû prévoir cela, donc je m’en excuse. J’ai supprimé cette fork.

  6. Discourse a renommé discourse-question-answer en discourse-upvotes. Ce changement de nom n’a pas eu d’impact matériel sur votre cas @Jaap-Jan_Swijnenburg, mais c’est la raison pour laquelle vous clonez maintenant (de manière inattendue) une fork de ce dépôt.

  7. Une migration dans discourse/discourse-upvotes (anciennement discourse-question-answer) suppose que la colonne value dans post_custom_fields est de type JSON.

  8. Les anciennes données créées par le plugin lorsqu’il était angusmcleod/discourse-question-answer (il y a des années) n’ont pas été enregistrées en tant que JSON valide par le concern HasCustomFields dans discourse/discourse. Je suppose, mais ces données ont probablement été ajoutées avant que la vérification de type JSON ne soit ajoutée il y a 4 ans (Il est toujours possible de se retrouver avec du JSON invalide dans les champs personnalisés enregistrés comme JSON dans des cas limites).

Par conséquent :

  1. Lorsque les personnes ayant l’URL (obsolète depuis des années) angusmcleod/discourse-question-answer dans leur app.yml mettent à jour leur Discourse, la migration dans la nouvelle version du plugin est clonée, la migration s’exécute et crée potentiellement cette erreur.

Il existe quelques solutions à cela :

  1. @Jaap-Jan_Swijnenburg dans votre cas, il vous suffit de supprimer la référence à mon ancien plugin QnA et vous pourrez reconstruire votre site. C’est tout ; rien de plus. Il semble que c’est ce que vous avez fait :+1:

  2. La migration du plugin discourse/discourse-upvotes pourrait être mise à jour pour gérer les valeurs non-JSON dans la colonne value de post_custom_fields.

Je noterais que la solution 2 gérerait également le cas supplémentaire des personnes qui souhaitent effectivement passer d’une ancienne version du plugin QnA à discourse-upvotes. Dans ce cas, la migration s’exécutera et échouera si des entrées dans la colonne value de post_custom_fields ne sont pas du JSON valide.

5 « J'aime »