Timeout 502/504 in Backend durante il salvataggio di modifiche importanti a post lunghi (~100k parole) a causa del collo di bottiglia di Diff

Durante la modifica e il salvataggio di post estremamente lunghi (circa 100.000 caratteri), abbiamo riscontrato un problema di timeout del backend. Il server diventa non rispondente durante l’operazione di salvataggio, generando errori 502/504. La console del frontend mostra il seguente stack di errori:

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

Ho eseguito alcuni test comparativi che suggeriscono che il collo di bottiglia si trova nel calcolo della differenza tra le versioni vecchia e nuova:

  • Modificare direttamente un lungo post A in un lungo post B e salvarlo innesca costantemente un timeout 502/504.
  • Cancellare innanzitutto il post lungo, salvare un segnaposto breve (ad esempio 5 caratteri), quindi incollare il contenuto nuovo completo B e salvarlo si completa rapidamente.

Sembra che il motore Diff attuale faticasse nei casi estremi che coinvolgono testo molto lungo combinato con un’elevata percentuale di modifiche. Sarebbe possibile aggiungere un meccanismo di fallback per le prestazioni? Ad esempio, quando il testo è estremamente lungo e il rapporto di modifica è elevato, il sistema potrebbe trattarlo come una “Riscrittura Completa” invece di eseguire un diff dettagliato riga per riga.

Il team ha in programma di ottimizzare la gestione del Diff per i post di grandi dimensioni, o di introdurre una sorta di degradazione graduale / protezione per tali scenari? Un’altra idea è consentire il salvataggio con successo prima, e calcolare il diff in modo asincrono in seguito.

2 Mi Piace

Nel frattempo, i log server-side di Unicorn hanno catturato il punto esatto del timeout, confermando che il worker è stato ucciso durante l’elaborazione della differenza del markdown:

Il worker di Unicorn ha ricevuto il segnale USR2 che indica che sta per scadere, dump del backtrace per il thread principale
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'
... 

Posso risolvere il problema sopra modificando UNICORN_TIMEOUT a 60 o 120?

Ehi,

Penso che sposterò questa discussione in Contribute > Bug. 100k caratteri è molto insolito, ma indipendentemente da ciò, penso che dovrebbe essere implementato un qualche tipo di fallback.