Adicionar profundidade máxima de aninhamento para detalhes recolhíveis

Gostaria de sugerir a adição de uma profundidade máxima de aninhamento para o recurso integrado [details], ou a introdução de uma configuração do site que permita aos administradores configurar esse limite.

O problema

Recentemente, um usuário no meu fórum Discourse criou uma publicação contendo 24 níveis de seções [details] aninhadas.

Isso causou vários problemas:

  1. Desempenho do navegador: Os usuários relataram que expandir múltiplos níveis fazia o Firefox ficar extremamente lento ou sem resposta.
  2. Tempo limite do endpoint Markdown: O acesso ao endpoint .md do tópico ficou extremamente lento. Observamos requisições levando 19,8 segundos e 31,1 segundos.
  3. Erros no servidor: O endpoint Markdown às vezes retornava uma página de erro “Oops”. Os logs do Discourse também mostravam avisos de tempo limite do worker Pitchfork durante a conversão para Markdown.
  4. Possível esgotamento de recursos: Como mecanismos de busca e rastreadores de IA solicitam endpoints .md com frequência, uma publicação profundamente aninhada poderia disparar repetidamente processamentos custosos e consumir recursos do servidor.

Após remover a publicação problemática, o endpoint Markdown retornou HTTP 200 e respondeu em aproximadamente 1,7 segundos.

O tópico afetado foi:

https://meta.appinn.net/t/topic/87672

(A resposta problemática já foi removida.)

Melhoria sugerida

Acho que seria útil:

  • Limitar o aninhamento de [details] a uma profundidade razoável, como 2 ou 3 níveis.
  • Adicionar uma configuração do site, como details_max_nesting_depth, permitindo que os administradores configurem a profundidade máxima de aninhamento.

Para compatibilidade reversa, a configuração poderia ter o valor padrão de ilimitado, permitindo que os administradores imponham um limite quando necessário.

Se os usuários excederem o limite configurado, o Discourse poderia rejeitar a publicação com uma mensagem de validação clara.

Solução temporária: um plugin

Criei um pequeno plugin que limita o aninhamento de [details] a um máximo de 2 níveis:

GitHub - scavin/discourse-details-depth-limit · GitHub

O plugin valida as publicações no lado do servidor e rejeita publicações que contenham mais de dois níveis de seções recolhíveis aninhadas.

Testei com sucesso em meu ambiente de desenvolvimento local do Discourse.

Para administradores que enfrentam problemas semelhantes, este plugin pode servir como uma solução temporária até que uma solução oficial esteja disponível.

Acredito que um limite configurável no plugin Details integrado seria uma salvaguarda útil contra aninhamento acidental ou excessivo.

2 curtidas

Olá @scavin, obrigado por reportar isso e por fornecer os detalhes de reprodução.

Estive investigando a lentidão no endpoint de Markdown que você descreveu e identifiquei um problema em MarkdownEndpoint::CookedProcessor#replace_details: elementos <details> aninhados estavam sendo convertidos repetidamente, resultando em um processamento exponencial.

Abri um PR de rascunho upstream com uma correção:

Com oito níveis de aninhamento, a correção reduziu as conversões recursivas de 255 para 8, com um aumento de velocidade de aproximadamente 31× no meu benchmark local. O PR passou nas verificações iniciais de CI do GitHub.

Também estou trabalhando na configuração de site details_max_nesting_depth que você propôs, dentro do plugin embutido de Detalhes, usando 0 para aninhamento ilimitado, a fim de preservar o comportamento existente. A implementação inicial está pronta, mas seus testes de integração ainda estão em andamento.

A correção de desempenho aborda o problema de conversão de Markdown no lado do servidor; o limite configurável forneceria uma salvaguarda adicional, especialmente para o desempenho no lado do navegador.

Acolheria com prazer feedback sobre a configuração proposta e se seria preferível incluí-la no mesmo PR ou enviá-la separadamente.

1 curtida

Obrigado pela investigação e correção rápidas!
Acho que seria melhor separá-los em duas PRs, para que a correção de desempenho possa ser revisada e mesclada de forma independente, sem precisar esperar pela nova configuração.
Também apoio o limite de profundidade configurável, com 0 como valor padrão para manter a compatibilidade reversa.

Obrigado @scavin. Vejo o benefício em separá-los, embora ambas as alterações tratem do mesmo relatório fundamental que você enviou e já estejam implementadas e testadas no CI. Tenho as edições do mantenedor habilitadas em todos os meus PRs, então estou disposto a seguir a preferência da equipe do Discourse, seja revisando os dois commits juntos ou separando-os.

1 curtida