@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.