Backend 502/504 Timeout ao salvar edições grandes em posts longos (~100k palavras) devido a gargalo no Diff

Ao editar e salvar posts extremamente longos (cerca de 100.000 caracteres), encontramos um problema de tempo limite no backend. O servidor torna-se inresponsivo durante a operação de salvamento, resultando em erros 502/504. O console do front-end exibe a seguinte pilha de erros:

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

Realizei alguns testes comparativos que sugerem que o gargalo está no cálculo da diferença entre as versões antiga e nova:

  • Editar diretamente um post longo A para um post longo B e salvar aciona consistentemente um tempo limite 502/504.
  • Limpar primeiro o post longo, salvar um marcador curto (por exemplo, 5 caracteres), colar todo o novo conteúdo B e salvar conclui-se rapidamente.

Parece que o mecanismo de diferença atual tem dificuldades com casos extremos envolvendo textos muito longos combinados com uma alta porcentagem de alterações. Seria possível adicionar um mecanismo de fallback de desempenho? Por exemplo, quando o texto é extremamente longo e a proporção de modificações é alta, o sistema poderia tratá-lo como uma “Reescrita Completa” em vez de realizar uma diferença detalhada linha por linha.

A equipe tem algum plano para otimizar o manuseio da diferença para posts grandes ou introduzir algum tipo de degradação graciosa/proteção para esses cenários? Outra ideia é permitir que o salvamento seja bem-sucedido primeiro e calcular a diferença de forma assíncrona depois.

Enquanto isso, os logs do Unicorn no lado do servidor registraram o ponto exato do tempo limite, confirmando que o processo foi encerrado durante o processamento do diff do markdown:

O worker do Unicorn recebeu o sinal USR2 indicando que está prestes a expirar o tempo limite, gerando o backtrace da thread principal
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 resolver o problema acima alterando UNICORN_TIMEOUT para 60 ou 120?

Ei,

Acho que vou mover isso para Contribute > Bug. 100k caracteres é muito incomum, mas, independentemente disso, acho que alguma alternativa deve ser implementada.

Em fevereiro, adicionei diff_too_complex: "O diff é complexo demais para ser exibido. Tente visualizar edições menores e individuais.". Nosso algoritmo de diff simplesmente para se as coisas ficarem complicadas demais.

Você está usando a versão mais recente aqui? Ele deve lidar com esses casos, a menos que você tenha um servidor muito, muito limitado.

Eu já estava na versão inicial deste ano, mas acabei de atualizar para a versão mais recente!

Após a atualização, consegui visualizar a mensagem “A diferença é muito complexa para ser exibida” e, sinceramente, achei ótimo. Pelo menos não trava completamente e ainda me permite prosseguir com a exclusão dos históricos de edição.

Também parece que o problema de congelamento/lentidão ao editar posts grandes pode ter sido resolvido. Ainda não tenho certeza, mas durante meu último teste, houve apenas um pequeno atraso e, felizmente, a versão editada foi processada com sucesso.

Vou fazer mais testes sobre isso. Muito obrigado!

Incrível :+1:

Acredito que o limite para “diff muito complexo” possa ser ajustado. Então, se você sentir que há essa necessidade, podemos resolver isso :+1: (há muitos fatores a considerar, então pode não haver uma solução única para todos)

Já testei isso várias vezes agora. Mesmo com edições complexas o suficiente para acionar a mensagem “A diferença é muito complexa para exibir”, o post nunca deixou de ser publicado novamente.

Acredito que esse problema foi completamente resolvido na versão mais recente. Mais uma vez, obrigado à equipe pelo excelente trabalho!