Problèmes avec Migrate_from_s3

When migrating from S3 to local storage, we see a number of issues.

The main issue is that the migrate_from_s3 rake task is not taking the Uploads table as a starting point, but the posts. This causes it to skip a lot of uploads which are being left on S3.

  • uploads used as logo’s because they are not referenced in a post
  • uploads for avatars because they are not referenced in a post
  • uploads that are (for some reason) referenced by their CDN URL in raw because they do not match the regex that is being used to identify the uploads
  • uploads that are on non-AWS S3 storage because they do not match the regex because it requires amazonaws in the URL
  • uploads that for some reason do not match the second, different regex (we’re seeing this with non-image uploads like mp3 files, not sure why this is happening)
2 « J'aime »

We’re working on improving the way we associate uploads to posts (by using the upload:// scheme) that will make these storage migrations much more bulletproof. There’s little point to fixing these rake tasks before that’s done.

7 « J'aime »

J’ai récemment ouvert une nouvelle PR pour permettre de migrer moins de publications à la fois (par exemple, une seule à la fois à des fins de test) et j’ai ajouté des tests pour cette tâche.

Il me semble logique de commencer par les publications, car vous souhaitez réécrire les publications pour mettre à jour l’URL dans le contenu rendu après chaque migration ; migrer tous les fichiers joints avant de lancer les réécritures laisserait le site fortement endommagé pendant potentiellement longtemps pour un gros site (je dois migrer environ 100 Go de S3 vers un stockage local, donc cela m’intéresse). Mais ce que j’ai écrit pourrait aider à démarrer l’écriture d’une tâche migrate_uploads_from_s3 qui serait exécutée après migrate_from_s3 afin de nettoyer les fichiers joints qui ne faisaient pas partie des publications.

@zogstrip Quel est l’état actuel de « Nous travaillons sur… » — est-ce toujours en évolution ou cette migration vaut-elle désormais la peine d’être surveillée ?

5 « J'aime »

Nous avons beaucoup travaillé sur le volet des téléchargements afin de garantir de meilleures associations entre les publications et les téléchargements.

Ces tâches de migration peuvent être améliorées à volonté :+1:

2 « J'aime »

Je découvrirai s’il vaut la peine de m’intéresser aux publications non liées aux messages une fois que je pourrai utiliser les envois par lots pour migrer mon site en dehors des heures de pointe ! :smiling_face: Merci pour la revue de la PR !

1 « J'aime »

J’ai deux points à aborder ensuite : Le premier est que la limite est utile, mais elle ne s’applique qu’à l’espace de recherche ; ensuite, je souhaite pouvoir spécifier un nombre maximal de publications à modifier. Je vais donc ajouter un nombre maximal de publications à modifier ainsi qu’une limite pour la requête.

En outre, lors de la spécification de max, il est logique d’être explicite sur ce qui est traité à des fins de débogage. Je souhaite donc rendre la sortie verbeuse si max n’est pas nil — cela permettra aux utilisateurs de valider le processus avant de continuer, car c’est le cas d’usage principal de ce travail.

Je pense que je vais spécifier max comme premier argument et une limite optionnelle comme deuxième, car en réalité, max est l’élément le plus important ; la limite sert simplement à rendre « un seul ping » moins coûteux.

Le deuxième point concerne les non-televersements : les téléversements. Il y a un peu plus d’un an, j’ai essayé de téléverser une vidéo sur le site Discourse où je m’inscrivais, alors que je cherchais désespérément à comprendre comment écrire la migration de Google+ vers Discourse. J’ai alors constaté que ce qui était écrit ressemblait à : https://#{SiteSettings.absolute_base_url}/original/3X/b/a/ba9e06ebc2f4397f26793bb5cd4e169308dd371d.mp4

Aujourd’hui, lorsque je téléverse une vidéo, j’obtiens quelque chose comme : ![file_example_MP4_480_1_5MG|video](upload://caJ9ykkpshw3PFK4464VUIPWJ4l.mp4).

Du moins, lors de mon test le plus récent, migrate_from_s3 a complètement déformé ces URL, les rendant même non reconnues comme des URL, ce qui doit absolument être corrigé. Ensuite, je pense que cette tâche est peu susceptible de rencontrer en pratique ![texte](non-upload-url-to-migrate), donc dans un premier temps, je souhaiterais simplement ajouter la syntaxe markdown de lien autour du protocole magique upload, plutôt que de rendre le regex plus complexe pour gérer les deux cas et le rendre encore plus difficile à lire. Mais je pourrais changer d’avis là-dessus.

Il semble que la balise video ou audio soit ajoutée en JavaScript via une correspondance regex. Je devrai donc copier les regex depuis app/assets/javascripts/discourse/app/lib/uploads.js dans la tâche pour les identifier correctement. J’inclurai la source des regex afin que la prochaine personne qui les trouve sache où les mettre à jour. :stuck_out_tongue:

Ce soir, j’ai trouvé du temps pour travailler sur ce sujet, et j’ai une proposition de pull request (PR) en cours. Elle n’est pas encore terminée ; je sais qu’il reste des bugs. Je ne pense pas avoir modifié le comportement des URL du pseudo-protocole upload: (normales pour les images) à ce stade, bien que j’aie ajouté une vérification de cohérence.

Avec les modifications de cette PR, j’ai réussi à migrer à la fois les téléversements normaux utilisant le pseudo-protocole upload: et les vidéos actuellement référencées explicitement par S3 (ou plutôt Digital Ocean Spaces dans mon cas). J’utilise cette commande pour modifier une seule publication à la fois :

bin/rake uploads:batch_migrate_from_s3[1,1000]

Notez que cela ne dépassera pas les 1000 premières publications retournées de manière quelque peu aléatoire par la requête de base de données ; la limite basse sert uniquement à accélérer la requête tout en migrant une seule publication à la fois, en vérifiant le comportement correct de cette publication, puis en recommençant pour en trouver une autre. Cette commande ne fonctionne ainsi qu’avec la PR sur laquelle je travaille actuellement !

Je continue d’ajouter des sorties de diagnostic au fur et à mesure que je travaille sur ce sujet, et je commence à penser qu’elles sont importantes au-delà du simple développement. Je constate de nombreuses échecs de téléchargement transitoires depuis Digital Ocean Spaces, où certains mais pas tous les téléchargements d’une publication sont migrés. Dans le scénario original, cela se traduirait simplement par l’affichage d’un . et la poursuite du processus, suivi de Done, mais en réalité, la tâche ne sera pas terminée. J’ai dû effectuer cinq ou six passes sur une seule publication avant que tous les fichiers ne soient migrés. (Je ne comptais pas, car je pensais d’abord déboguer un bug local.) Je m’attends à devoir exécuter cette migration à plusieurs reprises avec la même limite jusqu’à ce que les diagnostics soient propres. Par conséquent, j’affiche des progrès verbeux uniquement si max est défini, mais j’affiche des messages d’avertissement utiles dans tous les cas.

Actuellement, j’utilise l’astuce suivante pour pallier les échecs intermittents de téléchargement des espaces Discourse, ce qui, en pratique, a considérablement amélioré mon taux de réussite (trois tentatives ont été entièrement suffisantes sur des centaines de publications migrées jusqu’à présent).

https://github.com/johnsonm/discourse/commit/7dfac12a2ea6ec04ba4e0616b4e0dbd1d806cff7

J’ai également découvert que, pour une raison quelconque, nous nous sommes retrouvés avec des vidéos plus grandes que la limite que j’avais définie lors de l’importation depuis Google+. J’ai dû augmenter temporairement à la fois SiteSettings.max_image_size_kb et SiteSettings.max_attachment_size_kb lors de migrations ponctuelles de quelques vidéos trop volumineuses, dont il n’est pas clair comment elles ont fini sur le site, mais je ne veux pas les casser maintenant… Je ne sais pas si le bug permettant les téléversements trop volumineux provenait de mon script d’importation, de Discourse, ou simplement de ma mémoire des modifications apportées aux paramètres au fil du temps. :wink:

Comme une grande partie de ce que je migre provient d’une importation depuis G+, certaines de mes publications ont échoué aux validations actuelles. J’ai reçu quelques messages du type Échec non géré : Échec de la validation : Désolé, les nouveaux utilisateurs ne peuvent ajouter qu'une seule image dans une publication, et je n’ai pas initialement compris pourquoi ils ne se reproduisaient pas. Il s’avère que les téléversements ont été déplacés avec succès vers le stockage local et qu’ils utilisaient tous le pseudo-protocole upload:, donc le contenu brut n’a pas changé. Cependant, post.save! a échoué avec cette erreur de validation, empêchant post.rebake! de s’exécuter. J’ai donc quelques publications sur 30 000 contenant des images qui doivent être rebakeées ; malheureusement, je n’ai aucune trace de quelles sont ces publications. J’ai maintenant basculé vers post.save!(validate: false) comme autre correctif, de sorte que ce problème particulier ne devrait plus se reproduire. Je suis très heureux d’avoir fait en sorte que la migration s’arrête en cas d’erreurs non gérées, car sinon cela aurait potentiellement causé beaucoup plus de dégâts que quelques publications.

Pour maintenir mon site fonctionnel, y compris la livraison des notifications, tout en exécutant la migration, je ne veux pas saturer les files d’attente Sidekiq. Je sais que nommer les choses est l’un des deux problèmes les plus difficiles en informatique, avec l’invalidation du cache et les erreurs de décalage de un, mais je propose DISCOURSE_MIGRATION_MAX_ENQUEUED en tant que variable d’environnement pour définir le nombre total d’emplacements de file d’attente (pas d’emplacements de tâches) autorisés à être remplis lors de la migration d’un autre élément après un rebake pendant une migration, afin d’éviter de saturer les files d’attente et de permettre au site de continuer à fonctionner. J’ai un correctif qui ajoute cela, avec une valeur par défaut de zéro, pour tous les rebake par publication dans lib/tasks/uploads.rake. Je l’utilise pour ma migration en production.

https://github.com/discourse/discourse/blob/59a761851b9c8786d3a9692f8c595372b0534f77/lib/tasks/uploads.rake

4 « J'aime »

@zogstrip, pourrais-tu passer en revue cette PR, puisque tu as le contexte de la dernière revue que j’ai faite dans ce domaine ? FIX: Make migrations from S3 more robust; fix bare URL migration by johnsonm · Pull Request #10093 · discourse/discourse · GitHub

J’y ai inclus les correctifs que j’ai appliqués pendant l’exécution de cette migration relativement importante. Je n’ai pas essayé d’ajouter des tests pour chaque correctif ; je ne suis pas sûr de savoir comment injecter chaque type d’erreur. Mais au moins, la nouvelle fonctionnalité est testée.

@RGJ, je pense que ma PR, telle qu’elle est actuellement, pourrait résoudre tous vos points sauf les deux premiers, sauf que je ne suis pas sûr concernant le CDN. Mon site utilisait un CDN et a migré des vidéos ayant des URL CDN, mais cela aurait pu être un effet secondaire du nommage avec les espaces Discourse. Si vous avez d’autres cas, j’espère que ma PR vous fournira une base facile pour ajouter des variantes au regex et créer des cas de test supplémentaires.

Je pense qu’il est logique de migrer d’abord par publication, car après avoir migré les pièces jointes d’une publication, celle-ci doit être rebouclée afin que la version cuite contienne les bonnes URL. Une fois que j’aurai terminé la migration de mes publications (ce qui pourrait prendre moins de deux semaines maintenant que j’ai modifié ma limitation de débit pour vérifier directement la longueur de la file d’attente), je m’attacherai aux travaux restants à effectuer pour nettoyer.

Comme plusieurs publications peuvent partager des références au même contenu si plus d’une personne télécharge le même fichier, il faut une deuxième passe qui vérifie les données cuites pour détecter d’anciennes URL et reboucler ces publications afin d’adopter les nouvelles emplacements. Cela peut utiliser la même limitation de débit pour éviter de saturer les files d’attente.

Je ne devrais probablement voir aucun logo cassé sur makerforums, car nous avons ajusté la marque après avoir cessé de mettre du nouveau contenu dans « s3 » (pour nous, DigitalOcean Spaces), mais je verrai probablement encore beaucoup de pièces jointes stockées dans S3, au moins pour les avatars. La migration des pièces jointes non associées à une publication ne devrait être lancée qu’après la migration de toutes les publications, et je devrai probablement rédiger cela une fois que j’aurai terminé la migration des pièces jointes dans les publications.

@pfaffman, je vois Bizarre Problems with migrate_from_s3 - #5 qui décrit des erreurs qui ne se sont pas reproduites. Sans mes correctifs dans la PR actuelle, les erreurs sont ignorées silencieusement, y compris les échecs de validation. Je pense que le travail ici résoudra au moins certains des problèmes que vous avez rencontrés à l’époque.

@hosna, les problèmes que vous soulevez dans https://meta.discourse.org/t/what-does-rake-uploads-migrate-from-s3-exactly-do/97285 sont soit partiellement, soit complètement résolus pour l’instant dans cette PR. S’ils ne sont pas complètement résolus, j’ai ajouté des tests qui faciliteront l’ajout de tests supplémentaires pour valider d’autres correctifs.

@sam, puisque vous avez ajouté l’étiquette 2.6 à la PR, je suppose qu’elle ne sera pas fusionnée avant au moins quelques jours ; devrais-je intégrer mon travail sur la fonctionnalité de limitation de débit dans la PR avec les correctifs ? Ou préférez-vous garder les correctifs et le travail sur les fonctionnalités dans des PR séparées ? Je peux faire les deux. La fonctionnalité de limitation de débit fonctionne très bien ; je migre environ trois fois plus vite, sans impact sur la disponibilité du site, maintenant que j’attends que la file d’attente Sidekiq se vide, donc il semble logique de l’intégrer, si c’est quelque chose qui est normalement accepté dans les PR. Sinon, je dois attendre que la PR soit fusionnée pour le travail sur lequel elle se base, donc dans les deux cas, il serait bon d’avoir votre avis.

..

J’ai factorisé mon correctif de limitation de débit de migration et l’ai intégré à la PR. Cela fonctionne en pratique, et sar indique que je vois presque zéro temps d’inactivité en continu, tandis que le site continue de fonctionner, pendant la migration en direct. Un avantage du mode par lots est que je peux vérifier la disponibilité de nouvelles versions de Discourse après chaque lot complet de migrations ; j’ai mis à jour mon site vers la version 2.6.0beta1 dès que possible après sa sortie, et j’exécute les migrations avec succès sur 2.6.0beta1 avec ma PR de migration au-dessus depuis la mise à jour.

Je pense que la PR est prête pour la revue ; je prévois de soumettre une autre PR pour les dernières étapes, mais la mise en place de celle-ci améliorera l’expérience de migration générale pour tous, même avant que je n’achève les dernières parties.

5 « J'aime »

Eh bien, c’était il y a longtemps…

Je suis impatient de voir cela résolu. Pour l’instant, j’ai plusieurs sites sur multisite qui doivent récupérer des images depuis S3 (pour l’instant, je pense que certaines images sont locales et d’autres sur S3), puis les envoyer vers S3.

1 « J'aime »

@pfaffman C’est probablement une bonne chose que, lorsque j’ai commencé mon projet de migration, je ne savais pas ce que j’ai fini par comprendre depuis. Il semble que si j’avais utilisé minio client pour copier l’intégralité du bucket S3 dans le dossier local uploads, modifié tous les Upload.url à nil dans la console Rails, puis reconstruit le site, tout aurait été migré en quelques heures sans avoir à régénérer toutes les images. (À la place, je suis limité par le débit en relançant toutes les conversions d’images, comme si le CPU local était moins cher que de simplement copier toutes les images déjà traitées depuis S3.)

Et puis, si cela avait été aussi simple, je n’aurais effectué aucun de ces travaux pour rendre les migrations plus fiables en général, et personne d’autre n’en aurait bénéficié. :smiling_face:

4 « J'aime »

Ah. Cela ressemble à ce que je cherche à savoir. Peut-être que je vais essayer.

1 « J'aime »

Je prendrais… absolument une sauvegarde avant d’essayer cette approche, car je ne fais que spéculer. Je ne veux pas vous induire en erreur.

Ah, et une dernière chose : cela aurait complètement échoué pour les téléchargements audio et vidéo, et je ne l’aurais remarqué que plus tard, moment où j’aurais cherché à comprendre le problème et écrit du code personnalisé. Donc, si vous avez des téléchargements audio et vidéo, vous devez absolument commencer par là. Cela ne fonctionnera pas correctement sans la PR actuellement ouverte, qui ne sera fusionnée qu’après la version 2.5, puisque @sam l’a étiquetée 2.6.

2 « J'aime »

Toutes mes excuses de me joindre à la conversation si tard. Je viens de consulter votre PR et je me demande pourquoi vous recréez le modèle Upload au lieu de simplement modifier leur URL ? Et pourquoi ne pas simplement itérer sur OptimizedImages et faire de même ?

2 « J'aime »

@RGJ Je n’ai rien modifié à cela ; la recréation d’Upload était une correction de bug apportée par @zogstrip dans Cannot execute the rake uploads:migrate_from_s3 - #11

Je tente simplement de faire fonctionner le code déjà présent, et je ne connais pas bien les internals de Discourse ; j’ai beaucoup tâtonné dans le noir. Ma seule expérience en Ruby provient des quelques PR que j’ai réalisées pour Discourse. Suivre le modèle du code existant semble effectivement ne pas être la voie la plus efficace (voir ma conversation avec @pfaffman plus haut concernant la coupure courte), je suis tout à fait d’accord. Comme vous pouvez le constater, vu que plus tôt aujourd’hui je n’avais même pas réalisé que OptimizedImages.url devrait également être modifié pour un chemin /uploads et que l’etag devrait être défini sur nil (et je ne sais pas quoi d’autre), je continue d’agir à l’aveugle.

Il faut toujours parcourir les publications en premier, au moins pour corriger les anciennes URLs littérales dans les posts. Il reste encore d’autres corrections à apporter, comme ne pas revalider les posts et ne pas avaler silencieusement les erreurs. Je pense toujours qu’il faut limiter le débit pour réduire l’impact sur les sites en production.

Pour vos deux premières préoccupations concernant les mises à jour non liées aux posts, voici mon travail en cours, pas encore testé sur un site en production (commit) qui pourrait aider, mais que je ne testerai sur mon site en production qu’une fois la migration des uploads de posts terminée.

Ajuster quelque chose qui fonctionnait auparavant était tout ce que j’avais envie de faire. Si vous souhaitez effectuer une migration plus rapide, je suis tout à fait favorable ; il pourrait être judicieux de fusionner mon travail plus lent mais au moins meilleur en tant qu’amélioration de Pareto, puis vous pourriez le remplacer entièrement par quelque chose de bien meilleur, et je serai le premier à célébrer, même si je ne serai plus en mesure de l’utiliser à ce moment-là.

1 « J'aime »

@mcdanlj Merci pour votre explication. Je posais sincèrement une question, sans vouloir suggérer qu’il y a actuellement des problèmes. Je ne sais pas si la méthode que j’ai suggérée est vraiment « meilleure » — elle pourrait peut-être introduire de nombreux nouveaux problèmes. Je suppose que le code, tel qu’il est aujourd’hui, peu importe qui l’a écrit, l’est pour une raison.

3 « J'aime »

@RGJ Pareil, je suis sincère : si quelqu’un sait avec certitude comment éviter le gâchis de reconstruire toutes les images, je suis tout à fait pour. Et si j’étais un développeur Discourse expérimenté et que je savais le faire facilement, je l’aurais probablement fait dès le départ.

Je suppose que la migration loin de S3 n’est pas un cas courant pour ceux qui ont beaucoup d’images, donc il est difficile que cela vaille le temps investi, par rapport à ajouter des fonctionnalités plus généralement utiles à Discourse. J’avais environ 100 Go de fichiers téléchargés après l’importation depuis Google+ vers MakerForums, et nous avons choisi S3 en pensant que beaucoup de personnes pourraient migrer de ces communautés vers MakerForums. Mais au final, seules quelques communautés ont migré activement, donc la croissance continue ne justifiait plus le maintien sur S3. Je pense que c’est un cas assez extrême, et le retraitement des images n’est qu’un coût ponctuel.

Enfin, je suis très reconnaissant d’avoir ouvert ce sujet, car sinon j’aurais très facilement pu manquer les uploads non liés aux publications.

@RGJ Vous avez clairement raison : détruire et recréer n’est pas une bonne solution. J’ai ajouté une vérification : raise "Erreur : l'URL de l'upload #{url} a changé en #{new_upload.short_url}, elle devrait rester inchangée." if url != new_upload.short_url, ce qui permet au moins de signaler les problèmes liés à une source corrompue. La panne d’aujourd’hui de Digital Ocean Spaces m’a envoyé des données corrompues, ce qui a déclenché cette erreur pour de nombreux uploads — je ne sais pas combien. Mais comme l’ancien upload avait déjà été détruit, j’ai maintenant des pages corrompues, et je ne m’en suis rendu compte qu’après avoir perdu l’historique des logs indiquant quelles pages étaient corrompues. Je ne peux donc même pas les corriger manuellement à partir d’une sauvegarde.

Donc, bien que mon travail soit une amélioration par rapport à l’ancienne méthode car il signale au moins certaines erreurs, il serait beaucoup mieux de télécharger les fichiers, de vérifier les sommes de contrôle SHA1 des fichiers téléchargés, puis de les écrire dans des fichiers locaux. En attendant, j’ai modifié ma PR pour arrêter la migration en cas d’erreur non gérée, afin de limiter au moins la perte de données.

Je pense toujours que mon travail devrait être fusionné car il représente une amélioration de Pareto : il ne rend rien de pire et améliore la situation. Mais ce serait encore mieux de le faire correctement. Je pense que cela consisterait à écrire lib/file_store/from_s3_migration.rb en parallèle de lib/file_store/to_s3_migration.rb, mais je ne suis pas à la hauteur de cette tâche.

Ma PR n’ayant pas encore été examinée, j’y ai ajouté davantage de fonctionnalités. J’ai ajouté une tâche uploads:report_missing_uploads qui parcourt raw à la recherche d’instances de upload://... où l’objet upload n’existe pas. Au moins dans mon cas, avec les sauvegardes, je pourrai parcourir mes sauvegardes, trouver les fichiers orphelins et les restaurer sur le site, puis retravailler les publications concernées pour restaurer les images manquantes. J’en ai trouvé 678 à rechercher dans les sauvegardes, et j’en ai déjà retrouvé tous sauf 10, donc je suis content d’avoir écrit ce test ! Je devrai régler cela avant de passer à la phase suivante, où je retravaillerai les publications restantes.

J’ai terminé ma première phase de migration, sans inclure le retravail des publications affectées par des uploads partagés, ni les uploads non liés aux publications. Après avoir effectué une autre sauvegarde distante, je prévois de tester ces fonctionnalités également et de les ajouter à ma PR.

J’ai maintenant commencé à tester les phases suivantes de la migration : le retravail des publications et la migration des uploads non liés aux publications. Ma première leçon a été que le retravail comme étape suivante échoue à cause des avatars d’uploads non liés aux publications dans les citations, donc le retravail des publications doit être la dernière étape.

Découverte suivante : Merci aux contraintes de clés étrangères ! J’ai découvert, lors de la migration des uploads non liés aux publications, que je dois migrer au moins les profils avant de migrer généralement les uploads non liés aux publications.

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table "uploads" violates foreign key constraint "fk_rails_1d362f2e97" on table "user_profiles"

La migration des profils était délicate car je devais migrer deux uploads attachés au profil, mais dans certains cas, les gens utilisaient la même image pour les deux, donc j’ai dû effectuer ce travail en trois étapes. J’ai migré avec succès tous les profils de mon site avec des URLs S3.

J’ai migré tous mes uploads non liés aux publications et non liés aux profils. @RGJ, si vous voulez essayer la branche que j’ai publiée, elle est à jour avec mon travail. Tout ce qu’elle contient a maintenant été utilisé pour une migration complète de site.

@cvx Je ne sais pas quand vous aurez l’occasion de l’examiner, mais sans ma PR, migrate_from_s3 est définitivement rempli de bugs de destruction silencieuse de données. Ce que j’ai fait n’est pas parfait, mais cela protège contre de nombreux bugs que j’ai rencontrés en pratique.

J’ai terminé tout le travail que j’ai l’intention de faire ici pour le moment. J’ai migré mon site, ce qui signifie que je ne peux même plus évaluer efficacement les modifications demandées. Si vous rejetez cette PR, je vous suggère fortement de supprimer la migration existante, car elle détruirait silencieusement des données pour les utilisateurs.

En ce qui concerne la PR, je rencontre parfois des échecs de tests dans CI (comme la version actuelle), quelque chose comme ceci :

7867 exemples, 0 échec, 11 en attente, 1 erreur survenue en dehors des exemples

##[error]Process completed with exit code 1.

Cela ne se reproduit pas localement (jusqu’à présent) et je ne vois aucune information dans les logs de CI indiquant ce qui ne va pas. Je ne vais donc pas perdre plus de temps à essayer de fouiller dans la sortie de CI pour trouver des informations cachées.

Une dernière remarque : après avoir terminé la migration, nous avons découvert que les photos de profil de certains utilisateurs avaient été perdues lors de la migration, et ils les restaurent manuellement. Je suppose qu’un code supplémentaire aurait été nécessaire pour réussir cela, mais comme je ne l’ai découvert qu’une fois trop tard, je n’ai pas de cas de test pour valider cela. C’est donc un bug restant qui pourrait poser problème dans certaines configurations, mais je ne suis plus en mesure d’écrire la correction supplémentaire.

5 « J'aime »

Depuis que ma PR corrigeant la corruption silencieuse des données liée à migrate_from_s3 n’a même pas reçu un coup d’œil, peut-on au moins documenter migrate_to_s3 comme une voie à sens unique ?

Pour l’instant, c’est franchement un piège pour les débutants.

@cvx @zogstrip Quelle est votre préférence ? Examiner la PR ou simplement supprimer migrate_from_s3 et reconnaître honnêtement qu’il s’agit d’une voie à sens unique ?

5 « J'aime »

Désolé, c’est de ma faute. Je passerai la revue de la PR cette semaine.

7 « J'aime »

Le contenu de la revue indiquait essentiellement que la méthode actuelle est tellement erronée qu’il faut tout reconstruire à partir de zéro et d’une manière différente ; que la tentative de correction telle qu’elle était précédemment écrite n’est pas acceptable. Je ne suis pas prêt à cela, donc je pense vraiment que migrate_from_s3 devrait être entièrement supprimé et que migrate_to_s3 devrait être signalé comme une porte à sens unique qu’il vaut mieux ne jamais revenir en arrière. Actuellement, la présence de migrate_from_s3 dans le code source constitue une faille d’intégrité des données dans Discourse.

Je n’ai pas obtenu de revue en temps opportun pendant que je travaillais sur le processus de migration, et maintenant que j’ai depuis longtemps terminé la migration (avec certains résultats défectueux, comme des avatars cassés), je me trouve sans environnement de test pertinent. Je n’ai aucune confiance en ma capacité à le faire correctement, j’ai donc renoncé à ce combat. C’est au prochain pauvre imbécile qui pensera que c’est une bonne idée de stocker des images dans un service de stockage d’objets similaire à S3 de résoudre le problème. Désolé !

2 « J'aime »

@CxV Puisque vous avez rejeté la migration précédente en indiquant qu’elle avait été entièrement mal effectuée et qu’il fallait tout recommencer, veuillez examiner et fusionner cette correction du bug de corruption de données :

2 « J'aime »

Comme cela a été noté, j’ai rencontré des problèmes avec la migration que j’ai effectuée. Cela soutient le point de vue de @cvx selon lequel j’ai écrit la migration complètement à l’envers, et tant que quelqu’un ne la corrigera pas correctement, la suppression de la migration existante, pleine de corruptions de données silencieuses, devrait vraiment être fusionnée. (C’est un correctif très simple, la révision devrait être triviale. Plus elle sera fusionnée rapidement, moins il est probable que quelqu’un détruise son site en essayant de revenir en arrière à travers une porte à sens unique. Je ne sais pas comment plaider plus fermement en faveur d’une fusion ; si je le savais, je le ferais. Edit : Merci à @cvx pour l’approbation, la fusion et le suivi pour s’assurer que la migration de masse est marquée comme irréversible.)

Voici les problèmes connus que j’ai rencontrés :

  • Au moins l’avatar du discobot n’apparaissait pas ; toute la participation du discobot affichait l’avatar générique de personne (tête et épaules gris clair sur fond blanc).
  • Les avatars de certaines autres personnes n’ont pas été migrés correctement. Beaucoup ont été corrigés manuellement.
  • Lors de la configuration du site, l’administrateur original a expérimenté des modifications de la configuration “S3” (dans notre cas, Digital Ocean Spaces, avec et sans CDN), ce qui a entraîné la présence d’images optimisées orphelines qui n’ont pas été corrigées lors de la migration.

Pour toute personne ayant essayé d’utiliser ma branche et ayant vu certaines images disparaître de cette manière, j’ai exécuté un hack dans la console Rails, ce qui a corrigé certaines choses. Ce n’est pas la bonne façon de faire cela, je ne connais tout simplement pas assez le modèle pour le faire correctement. Mon niveau en Ruby est très faible ; je ne touche pas à Ruby en dehors de mes petites contributions à Discourse.

Mais, tel quel, ce terrible hack a corrigé les images cassées (issues des erreurs de configuration initiales) et a au moins permis de rétablir l’avatar du discobot (et peut-être d’autres, mais tous ceux dont j’avais déjà connaissance avaient déjà été réparés).

Ce qui n’apparaît pas ici, c’est tout ce que j’ai fait entre les étapes, en examinant chaque ensemble au fur et à mesure. Cela faisait partie d’une session d’“exploration de ce qui existe dans la console Rails” et n’était pas réellement un script que j’ai écrit et exécuté. Il n’y a aucune gestion des erreurs, et j’ai effectué une sauvegarde complète du site avant de commencer tout ce travail.

Je ne sais pas comment dire plus fortement que ce code n’est pas la façon idiomatique de Ruby on Rails de procéder à cette réparation. Je voulais simplement partager comment j’ai réparé au moins une partie des dégâts que je m’étais causés lors de ma tentative précédente de migrer mon site hors de Digital Ocean Spaces.

require 'set'

uploadids = Set.new
optimizedimages = Set.new
OptimizedImage.where("url like '%UNIQUEPARTOFS3URL%'").each do |oi|
  uploadids.add(oi.upload_id)
  optimizedimages.add(oi)
end

postids = Set.new
uploadids.each do |u|
  PostUpload.where(upload_id: u).each do |pu|
    postids.add(pu.post_id)
  end
end

optimizedimages.each do |oi|
  oi.delete
end

postids.each do |pid|
  Post.where(id: pid).each do |p|
    p.rebake!
  end
end
2 « J'aime »