Erreur Backend 502/504 lors de la sauvegarde de modifications majeures sur de longs articles (~100k mots) en raison d'un goulot d'étranglement Diff

Lors de l’édition et de la sauvegarde de publications extrêmement longues (environ 100 000 caractères), nous avons rencontré un problème de délai d’attente côté serveur. Le serveur devient non responsive pendant l’opération de sauvegarde, ce qui entraîne des erreurs 502/504. La console du navigateur affiche la pile d’erreurs suivante :

ajax-error.js:36:15
l ajax-error.js:36
u ajax-error.js:75
d ajax-error.js:84
Ember 41
update rest.js:72
update rest.js:72
save rest.js:115
editPost composer.js:1147
Ember 6

J’ai effectué quelques tests comparatifs qui suggèrent que le goulot d’étranglement se situe dans le calcul de la différence (diff) entre l’ancienne et la nouvelle version :

  • La modification directe d’une longue publication A en une longue publication B et sa sauvegarde déclenchent systématiquement un délai d’attente 502/504.
  • Effacer d’abord la longue publication, sauvegarder un court texte temporaire (par exemple 5 caractères), puis coller le contenu complet B et sauvegarder se termine rapidement.

Il semble que le moteur de Diff actuel peine dans les cas extrêmes impliquant un texte très long combiné à un taux de modifications élevé. Serait-il possible d’ajouter un mécanisme de repli en cas de problème de performance ? Par exemple, lorsque le texte est extrêmement long et que le ratio de modification est élevé, le système pourrait le traiter comme une « Réécriture complète » au lieu d’effectuer une différence détaillée ligne par ligne.

L’équipe a-t-elle prévu d’optimiser la gestion des Diff pour les publications volumineuses, ou d’introduire une forme de dégradation gracieuse / protection pour ce type de scénario ? Une autre idée serait de permettre la sauvegarde de réussir en premier, puis de calculer la différence de manière asynchrone par la suite.

Pendant ce temps, les logs serveur de Unicorn ont capturé le moment exact du timeout, confirmant que le worker a été tué lors du traitement du diff Markdown :

Unicorn worker received USR2 signal indicating it is about to timeout, dumping backtrace for main thread
config/unicorn.conf.rb:204:in `backtrace'
config/unicorn.conf.rb:204:in `block (2 levels) in reload'
/var/www/discourse/lib/discourse_diff.rb:172:in `[]'
/var/www/discourse/lib/discourse_diff.rb:172:in `tokenize_markdown'
/var/www/discourse/lib/discourse_diff.rb:115:in `side_by_side_markdown'
/var/www/discourse/app/serializers/post_revision_serializer.rb:128:in `body_changes'
... 

Puis-je résoudre le problème ci-dessus en modifiant UNICORN_TIMEOUT à 60 ou 120 ?

Salut,

Je pense que je vais déplacer cela dans Contribute > Bug. 100k caractères est très inhabituel, mais de toute façon, je pense qu’une solution de repli devrait être mise en œuvre.

En février, j’ai ajouté diff_too_complex: "Le diff est trop complexe à afficher. Veuillez essayer de consulter les modifications plus petites individuellement.". Notre algorithme de diff s’arrête simplement si les choses deviennent trop compliquées.

Est-ce que vous utilisez la dernière version ici ? Il devrait gérer ces cas, sauf si vous avez un serveur très très peu puissant.

J’avais utilisé la version préliminaire de cette année plus tôt, mais je viens de passer à la toute dernière version !

Après la mise à jour, j’ai pu voir avec succès le message « La différence est trop complexe pour être affichée », et honnêtement, c’est génial. Au moins, ça ne plante pas brutalement et ça me permet toujours de continuer et de supprimer l’historique des modifications.

On a aussi l’impression que le problème de gel/lenteur lors de l’édition de très longs messages est peut-être résolu. Je n’en suis pas encore certain, mais lors de mon dernier test, ça a lagué un court instant puis, heureusement, la version modifiée a bien été traitée.

Je vais effectuer d’autres tests à ce sujet. Merci beaucoup !

Magnifique :+1:

Je pense que le seuil « diff trop complexe » peut être ajusté, donc si vous estimez que c’est nécessaire, nous pouvons trouver une solution ensemble :+1: (il y a beaucoup de facteurs à prendre en compte, donc il n’y aura peut-être pas de solution universelle)

Je l’ai testé à plusieurs reprises maintenant. Même avec des modifications suffisamment complexes pour déclencher l’avertissement « La différence est trop complexe à afficher », le message n’a jamais échoué à être publié à nouveau.

Je crois que ce problème a été entièrement résolu dans la dernière version. Merci encore à l’équipe pour ce excellent travail !