Backend 502/504 Timeout beim Speichern größerer Änderungen an langen Beiträgen (~100k Wörter) aufgrund von Diff-Engpass

Beim Bearbeiten und Speichern extrem langer Beiträge (ca. 100.000 Zeichen) sind wir auf ein Backend-Timeout-Problem gestoßen. Der Server reagiert während des Speichervorgangs nicht mehr, was zu 502/504-Fehlern führt. Die Konsole der Benutzeroberfläche zeigt den folgenden Fehler-Stack:

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

Ich habe einige Vergleichstests durchgeführt, die darauf hindeuten, dass der Flaschenhals in der Berechnung der Differenz zwischen der alten und der neuen Version liegt:

  • Das direkte Bearbeiten eines langen Beitrags A in einen langen Beitrag B und das anschließende Speichern löst konsistent ein 502/504-Timeout aus.
  • Das Löschen des langen Beitrags, das Speichern eines kurzen Platzhalters (z. B. 5 Zeichen), das Einfügen des vollständigen neuen Inhalts B und das anschließende Speichern erfolgt schnell.

Es scheint, dass die aktuelle Diff-Engine mit extremen Fällen kämpft, bei denen sehr langer Text mit einem hohen Änderungsanteil kombiniert ist. Wäre es möglich, einen Leistungs-Backup-Mechanismus hinzuzufügen? Zum Beispiel könnte das System bei extrem langen Texten und einem hohen Änderungsverhältnis den Vorgang als „Vollständige Neuschreibung“ behandeln, anstatt eine detaillierte zeilenweise Diff-Berechnung durchzuführen.

Hat das Team Pläne, die Diff-Verarbeitung für große Beiträge zu optimieren oder eine Art graceful degradation / Schutz für solche Szenarien einzuführen? Eine weitere Idee wäre, das Speichern zunächst erfolgreich abzuschließen und die Diff-Berechnung asynchron im Hintergrund durchzuführen.

In der Zwischenzeit haben die Server-seitigen Unicorn-Logs den genauen Zeitpunkt des Timeouts erfasst und bestätigt, dass der Worker während der Verarbeitung des Markdown-Diffs getötet wurde:

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

Kann ich das oben genannte Problem lösen, indem ich UNICORN_TIMEOUT auf 60 oder 120 ändere?

Hey,

Ich denke, ich werde das in Contribute > Bug verschieben. 100k Zeichen sind sehr ungewöhnlich, aber unabhängig davon sollte meiner Meinung nach ein Fallback implementiert werden.

Im Februar habe ich `diff_too_complex: „Der Diff ist zu komplex, um angezeigt zu werden. Bitte versuchen Sie, einzelne kleinere Änderungen anzuzeigen.“` hinzugefügt. Unser Diff-Algorithmus bricht einfach ab, wenn es zu kompliziert wird.

Hast du hier die neueste Version im Einsatz? Sie sollte diese Fälle behandeln, es sei denn, du hast einen sehr, sehr schwachen Server.

Ich habe die frühe Version von diesem Jahr schon mal ausprobiert, aber ich bin gerade auf die absolut neueste Version aktualisiert!

Nach dem Upgrade habe ich die Meldung „Der Unterschied ist zu komplex, um angezeigt zu werden“ erfolgreich gesehen, und ehrlich gesagt, ist das großartig. Zumindest stürzt es nicht mehr hart ab und ermöglicht es mir trotzdem, die Bearbeitungsverläusche zu löschen.

Es fühlt sich auch so an, als ob das Einfrieren/Verzögern beim Bearbeiten großer Beiträge jetzt behoben sein könnte. Ich bin mir noch nicht ganz sicher, aber während meines letzten Tests gab es nur eine kurze Verzögerung, und dann wurde die bearbeitete Version glücklicherweise erfolgreich verarbeitet.

Ich werde das weiter testen. Vielen Dank!

Fantastisch :+1:

Ich glaube, die Schwelle für „diff zu komplex“ kann angepasst werden. Wenn du das für notwendig hältst, können wir das herausfinden :+1: (Es gibt viele Faktoren zu berücksichtigen, daher gibt es möglicherweise keine Lösung, die für alle Fälle passt)

Ich habe dies mittlerweile mehrfach getestet. Selbst bei Änderungen, die komplex genug sind, um die Meldung „Der Diff ist zu komplex, um angezeigt zu werden“ auszulösen, ist der Beitrag nie wieder fehlgeschlagen.

Ich bin überzeugt, dass dieses Problem in der neuesten Version vollständig behoben wurde. Nochmals vielen Dank an das Team für die großartige Arbeit!