Les téléchargements ne sont pas orphelins et purgés

Salut,

Récemment, je suis devenu le dernier administrateur et mainteneur d’une instance basique d’image Docker Discourse qui a été initialement installée sur notre serveur en 2021 (je pense) et principalement mise à jour par quelqu’un d’autre. Depuis un certain temps, peut-être dès le début, nous avons un problème avec les téléchargements de messages supprimés de manière logicielle qui ne sont pas orphelins et purgés, et j’essaie de résoudre ce problème à nouveau depuis quelques jours car les fichiers obsolètes continuent de s’accumuler et de gaspiller de l’espace de stockage. Nous n’utilisons pas S3 et nous avons suffisamment de stockage pour les téléchargements que nous souhaitons réellement conserver.

J’ai migré le fichier de sauvegarde complet de Discourse, y compris les téléchargements, vers un serveur de staging séparé pour les tests en reconstruisant avec notre app.yml en suivant les guides officiels d’installation de Docker Discourse, puis en restaurant la sauvegarde depuis la ligne de commande. Les deux installations semblent fonctionner de manière identique sans autres problèmes évidents, mais le problème de téléchargement persiste.

Je n’arrive pas à trouver d’erreurs pertinentes dans les journaux et Sidekiq exécute les tâches de nettoyage comme prévu. J’ai exécuté rake db:migrate sur la version de staging et reconstruit plusieurs fois, essayé de détruire définitivement des messages et vérifié les paramètres. Après avoir supprimé définitivement certains messages directement depuis la console Rails et essayé d’exécuter manuellement la tâche de nettoyage, j’ai remarqué que le répertoire des “tombstones” avait légèrement augmenté de taille à un moment donné et qu’il y avait déjà quelques fichiers au départ, donc le mécanisme devait fonctionner dans certaines situations, n’est-ce pas ? À en juger par la faible augmentation de taille, presque tous les fichiers obsolètes ne sont toujours pas détectés comme orphelins.

Les paramètres actuels pertinents du panneau d’administration sont listés ci-dessous. Puis-je régler les derniers à 0 pour ignorer efficacement les périodes de grâce pendant les tests ?

nettoyer les téléchargements = true
délai de grâce pour les téléchargements orphelins (heures) = 1
délai de grâce pour la purge des téléchargements supprimés (jours) = 1

Comment puis-je résoudre ce problème efficacement ? Je suis à l’aise avec la ligne de commande mais mes compétences en base de données sont rudimentaires, donc j’apprécierais vraiment quelques conseils pour éviter de passer en revue tous les détails possibles de la configuration du serveur sans savoir ce que je cherche à ce stade.

J’ai cherché et lu désespérément sur ce forum des cas similaires, mais il n’y en a que quelques-uns et ces fils de discussion semblent s’arrêter soit dans une impasse, soit à des solutions manuelles pour des fichiers uniques, donc pas directement adaptés à ce cas d’utilisation.

N’hésitez pas à me demander plus de détails si nécessaire, je fais de mon mieux pour résoudre ce problème définitivement.

3 « J'aime »

Bonjour et bienvenue @Uphill4721 :slight_smile:

Je pense qu’il y a des informations pertinentes dans ces sujets, si ma mémoire est bonne :

1 « J'aime »

Merci pour la réponse rapide !

Ces sujets et quelques autres qui y sont liés me sont devenus assez familiers en essayant de résoudre ce problème, mais malheureusement, ils n’ont apporté aucune solution définitive à ce problème.

Hier, sur le serveur de staging, j’ai exécuté ces commandes modifiées pour les sujets et les messages supprimés il y a plus de 9 jours :

Après cela, j’ai remarqué une légère augmentation de la taille du contenu du répertoire des “tombstones” et je surveille toujours la situation en raison de la période de grâce. Je me demande toujours si la modification des paramètres pertinents à zéro heure/jour contournerait le temps d’attente pendant les tests.

Plus tôt, sur le serveur d’origine, j’ai essayé de supprimer des téléchargements des révisions de messages les plus récentes, mais les fichiers étaient toujours disponibles après la période de grâce.

À ce stade, je serais personnellement ravi de trouver une solution manuelle fonctionnelle pour supprimer définitivement ne serait-ce qu’un seul sujet avec ses messages et ses téléchargements non référencés ailleurs, mais cela pourrait être un gros problème pour d’autres personnes utilisant Discourse, en supposant naturellement que les paramètres de nettoyage dans le panneau d’administration seraient efficaces comme décrit, mais sans nécessairement remarquer si ce n’est pas le cas et se retrouver avec des téléchargements potentiellement sensibles censés être supprimés définitivement, mais qui restent en fait sur le système de fichiers. Notre problème ne concerne heureusement que le stockage gaspillé, mais pour quelqu’un d’autre, cela pourrait être bien pire.

Il y a une autre mention similaire datant d’il y a seulement deux mois :

Alors, des conseils sur la façon de déterminer s’il s’agit d’une mauvaise configuration de notre côté ou d’un véritable bug ? Nous sommes très satisfaits de Discourse par ailleurs et je suis très motivé à résoudre ce problème et à aider les autres en cours de route.

1 « J'aime »

Ceci est purement spéculatif, mais d’après un rapide coup d’œil aux modèles post, post_upload et upload, vous pouvez probablement découvrir si vous avez des uploads orphelins (objets de base de données) avec ceci :

Upload.find_by_sql("select * from uploads where id in (select upload_id from post_uploads where post_id not in (select id from posts))")

Je n’ai pas testé cela, donc je ne peux pas être sûr si cela trouvera correctement les uploads orphelins ou même s’exécutera sans erreur. Au cas où cela ne fonctionnerait pas tel quel et que quelqu’un d’autre pourrait le faire fonctionner, ainsi que pour toute autre personne intéressée, je vais détailler l’intention.

  1. Upload.find_by_sql() renvoie une collection d’objets Upload qui correspondent à la requête SQL fournie.
  2. (select id from posts) obtient tous les ID des posts existants.
  3. (select upload_id from post_uploads where post_id not in () obtient tous les ID des post_uploads pour lesquels aucun post n’existe.
  4. select * from uploads where id in () obtient tous les uploads correspondant à ces ID de post_uploads.

Ce n’est qu’une piste possible à explorer, malheureusement je ne connais pas assez bien le système d’uploads pour vraiment contribuer davantage, sauf pour dire que ce qui précède ne tient pas compte de toutes les situations. Les posts modifiés plutôt que supprimés en sont un exemple évident.

Il existe également d’autres types d’uploads non pris en compte, comme les uploads d’utilisateurs, qui, je suppose, sont des choses comme le téléchargement d’une photo de profil.

Les plugins peuvent également créer et conserver des uploads, je ne sais pas ce qu’il advient de ceux-ci si, par exemple, le plugin est supprimé. Je pense que les données du plugin restent dans la base de données après la suppression d’un plugin, ce qui signifie potentiellement que tous les uploads créés par ce plugin ne sont jamais supprimés dans cette situation.

4 « J'aime »

Merci pour votre réponse !

La requête fonctionne, mais elle n’affiche que deux téléchargements et leurs détails. Il devrait y avoir des centaines ou des milliers de téléchargements correspondant aux critères orphelins, la plupart étant des fichiers image initialement téléchargés par les utilisateurs lors de publications normales.

Nous utilisons actuellement uniquement des plugins officiels :

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-chat-integration.git
          - git clone https://github.com/discourse/discourse-prometheus.git
          - git clone https://github.com/discourse/discourse-bbcode-color
          - git clone https://github.com/discourse/discourse-data-explorer

Il y a eu une sorte de refonte du processus de téléchargement peu après notre installation initiale, je me demande si cela pourrait être lié à notre situation : A new era for file uploads in Discourse

La période de grâce aurait dû être dépassée sur le serveur de staging maintenant, mais je ne vois aucun effet sur la taille du répertoire de téléchargement et les fichiers de test sont toujours disponibles. Que devrais-je chercher ensuite ? Cela pourrait-il être causé par des permissions de système de fichiers défectueuses ou quelque chose de similaire, existe-t-il un moyen facile de vérifier ? Je manque d’idées de cibles spécifiques, tout le reste fonctionne très bien et c’est le seul problème que nous avons actuellement.

En parcourant des sujets similaires pour recueillir des cas non résolus potentiellement correspondants, voici un bon exemple de la façon dont ces situations peuvent même entraîner des problèmes juridiques en raison des téléchargements d’utilisateurs qui ne sont pas orphelins et définitivement supprimés comme ils le devraient :

Une autre situation similaire datant de 2016 :

Ces types de conditions créent une énorme ouverture aux abus et même aux attaques ciblées pour le téléchargement de contenu illégal qui pourrait ne pas être définitivement supprimé du serveur, même lorsque les administrateurs pensent que ce serait le cas. Bien sûr, supprimer des fichiers individuels manuellement directement depuis le système de fichiers est possible, mais je ne pense pas que les gens devraient être obligés de suivre cette voie pour un besoin aussi basique, surtout lorsqu’il existe un paramètre d’interface graphique indiquant un processus de purge automatique et que les modérateurs n’ont souvent pas un accès direct au serveur. De plus, la suppression manuelle n’est pas pratique avec des tas de fichiers dispersés dans différents sujets supprimés.

Y a-t-il ici suffisamment de bases pour un rapport de bug réel ? Je n’exclus pas une éventuelle mauvaise configuration de notre côté, mais je suis déconcerté par le manque de messages d’erreur et tout le reste semble fonctionner correctement. J’ai passé un nombre croissant de jours à dépanner et à tester, acquérant plus de connaissances sur Discourse et ses composants au cours du processus, donc je pense qu’avec quelques conseils, je pourrais aider à déterminer s’il existe un détail de cas extrême déclenchant ce comportement étrange. J’espère qu’il est acceptable de mentionner @zogstrip à ce stade ?

Pour une solution temporaire, est-il possible de déplacer manuellement tous les téléchargements dans le répertoire de la corbeille et d’utiliser les méthodes de récupération des téléchargements pour ne restaurer que les fichiers non orphelins dans leurs répertoires corrects ? J’ai en fait essayé de faire cela aujourd’hui, mais rake uploads:recover_from_tombstone n’a restauré aucun fichier. Cela pourrait-il indiquer un problème plus important avec les entrées de la base de données des téléchargements ?

Bonjour. Je rencontre le même problème ou un problème similaire, je n’arrive pas à comprendre pourquoi les fichiers ne peuvent pas être supprimés. Quelqu’un d’autre rencontre-t-il encore ce problème ?
J’ai exécuté quelques requêtes SQL et les références de téléchargement « bloquées » semblent être toutes des Brouillons, mais j’ai vérifié mes Brouillons et ceux des autres utilisateurs, et il n’y en a aucun. Les tables de Brouillons sont vides.
Le nettoyage des orphelins est activé et les paramètres sont configurés pour supprimer les orphelins aussi rapidement que possible.
J’ai joint une requête SQL.

SELECT 
    uploads.original_filename,
    ROUND(uploads.filesize / 1000000.0, 2) AS size_in_mb,
    uploads.extension,
    uploads.created_at,
    uploads.url,
    upload_references.upload_id,
    upload_references.target_id,
    upload_references.target_type,
    upload_references.created_at,
    upload_references.updated_at
FROM upload_references
JOIN uploads ON uploads.id = upload_references.upload_id
ORDER BY uploads.filesize DESC
LIMIT 250

sql.csv (46,1 Ko)

Cela se produit depuis que j’ai installé le forum. Même lorsqu’il n’y avait pas de thèmes personnalisés ni de plugins installés.
Même l’ancien logo du forum que j’ai téléchargé plusieurs fois (le premier fichier jamais téléchargé) est toujours référencé comme Brouillon et se trouve toujours dans le dossier des téléchargements. :man_facepalming:
Théoriquement, je pourrais filtrer toutes les références de téléchargement et filtrer les Brouillons par target_type, puis supprimer de la base de données… et laisser les tâches sidekiq gérer le nettoyage (ai-je raison ?)
mais j’utilise une instance auto-hébergée et je suis assez nouveau sur Discourse, donc je préfère demander ici…
Ce serait une solution de contournement, mais il reste une question : pourquoi cela se produit-il ?

J’espère que quelqu’un aura des suggestions, mon espace disque augmente de façon exponentielle :smile:

1 « J'aime »

Oui, nous avons toujours ce problème.

J’aimerais vraiment le résoudre d’une manière ou d’une autre, notre forum reçoit beaucoup de téléchargements, mais seule une fraction d’entre eux doit être conservée à long terme, donc beaucoup d’espace disque est gaspillé. Toutes suggestions de dépannage sont les bienvenues.

Intéressé par cela comme solution temporaire, si c’est pratique. :thinking:

J’ai installé le forum il y a 2 semaines et il a ce problème depuis le début. On dirait un bug.
Pouvez-vous exécuter la même requête SQL et vérifier s’il y a beaucoup de références “Brouillons” bloquées ? C’est facile à voir, j’en ai des dizaines, mais dans la table des brouillons, il y en a 2 ou 3 réels. On dirait qu’ils ne sont pas supprimés après modification (n’étant plus un brouillon, mais une référence laissée dans la base de données chaque fois qu’un message est modifié par exemple).

Je dois comprendre comment supprimer une entrée de référence de la base de données et supprimer d’abord les références d’un fichier, puis vérifier si la tâche de nettoyage fonctionne.
Je ne sais pas à quel point c’est sûr, mais ces innombrables entrées de Brouillons me semblent tout simplement incorrectes.

Je peux fournir des journaux au personnel/développeurs, je suis juste nouveau sur Discourse et je ne sais pas quels fichiers journaux seraient utiles.

EDIT :
J’essaie de comprendre la structure de la base de données, et puis-je supprimer ces entrées de téléchargement sans autres problèmes (je ne veux pas manquer de relations importantes dans la base de données). Je ne comprends pas non plus ce que sont exactement les draft_sequences.
Mais je dois dupliquer mon forum de production sur une VM locale, seulement alors je pourrai tester…

Un autre sujet pertinent, j’ai posté là-bas car je n’étais pas au courant de ce sujet.

Je pense que la seule façon de vraiment supprimer une image de manière automatique est de la supprimer manuellement du message avant de le supprimer. Mais je ne suis pas entièrement sûr que cela fonctionne non plus. J’utilise des paramètres identiques aux vôtres concernant la purge (mais j’utilise un stockage compatible S3) et je peux également confirmer que les images ne sont jamais purgées si le seul message contenant cette image (plusieurs messages peuvent contenir la même image, y compris les avatars et les bannières d’utilisateurs) est supprimé.

J’utilise cette solution pour rechercher si une image est utilisée dans d’autres messages, qui a été fournie par @RGJ

Ce serait vraiment formidable si cela pouvait être fait automatiquement. Particulièrement parce que Discourse gère les images de manière intelligente, en évitant de créer des fichiers dupliqués si de nombreux messages utilisent la même image. Le revers de la médaille est qu’il est très fastidieux de supprimer des images individuelles qui ont été utilisées à plusieurs reprises.

J’ai eu quelqu’un qui a spammé du contenu qui nécessitait une suppression urgente via plusieurs comptes auparavant, et il a été très stressant d’essayer de gérer cela et de s’assurer qu’il était entièrement supprimé (tous les fichiers originaux, les fichiers optimisés, le cache CDN, les messages, les avatars, les bannières d’utilisateurs, etc.).

J’ai fait cette suggestion de fonctionnalité, car elle serait très utile à mon avis. Si cela était implémenté, ainsi que la purge automatique du contenu contenu dans les messages supprimés, je pense que tous les cas seraient couverts et pourraient être gérés sans accès SSH.

1 « J'aime »