Añadir una profundidad máxima de anidación para los detalles plegables

Me gustaría sugerir la adición de una profundidad máxima de anidación para la función integrada [details], o la introducción de una configuración del sitio que permita a los administradores configurar este límite.

El problema

Recientemente, un usuario en mi foro de Discourse creó una publicación que contenía 24 niveles de secciones [details] anidadas.

Esto causó varios problemas:

  1. Rendimiento del navegador: Los usuarios informaron que expandir varios niveles hacía que Firefox se volviera extremadamente lento o no respondiera.
  2. Tiempo de espera del endpoint Markdown: El acceso al endpoint .md del tema se volvió extremadamente lento. Observamos peticiones que tardaban 19,8 segundos y 31,1 segundos.
  3. Errores del servidor: El endpoint Markdown a veces devolvía una página de error “Oops”. Los registros de Discourse también mostraron advertencias de tiempo de espera del trabajador Pitchfork durante la conversión de Markdown.
  4. Posible agotamiento de recursos: Dado que los motores de búsqueda y los rastreadores de IA solicitan con frecuencia los endpoints .md, una publicación con un anidamiento profundo podría desencadenar repetidamente un procesamiento costoso y consumir recursos del servidor.

Después de eliminar la publicación problemática, el endpoint Markdown devolvió HTTP 200 y respondió en aproximadamente 1,7 segundos.

El tema afectado fue:

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

(El comentario problemático ya ha sido eliminado.)

Mejora sugerida

Creo que sería útil hacer una de las siguientes cosas:

  • Limitar el anidamiento de [details] a una profundidad razonable, como 2 o 3 niveles.
  • Añadir una configuración del sitio, como details_max_nesting_depth, que permita a los administradores configurar la profundidad máxima de anidamiento.

Por compatibilidad hacia atrás, la configuración podría tener un valor predeterminado de ilimitado, permitiendo a los administradores aplicar un límite cuando sea necesario.

Si los usuarios superan el límite configurado, Discourse podría rechazar la publicación con un mensaje de validación claro.

Solución temporal: un plugin

He creado un pequeño plugin que limita el anidamiento de [details] a un máximo de 2 niveles:

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

El plugin valida las publicaciones en el lado del servidor y rechaza las publicaciones que contienen más de dos niveles de secciones plegables anidadas.

Lo he probado con éxito en mi entorno de desarrollo local de Discourse.

Para los administradores que experimenten problemas similares, este plugin puede servir como solución temporal hasta que esté disponible una solución oficial.

Creo que un límite configurable en el plugin Detalles integrado sería una salvaguarda útil contra el anidamiento accidental o excesivo.

3 Me gusta

Hola @scavin, gracias por reportar esto y por proporcionar los detalles de reproducción.

He estado investigando la ralentización del endpoint de Markdown que describiste y he identificado un problema en MarkdownEndpoint::CookedProcessor#replace_details: los elementos <details> anidados se estaban convirtiendo repetidamente, lo que resultaba en un procesamiento exponencial.

He abierto un PR en borrador upstream con una corrección:

https://github.com/discourse/discourse/pull/44461

Con ocho niveles de anidación, la corrección redujo las conversiones recursivas de 255 a 8, con una aceleración aproximada de 31 veces en mi benchmark local. El PR ha superado sus comprobaciones iniciales de CI de GitHub.

También estoy trabajando en la configuración de sitio details_max_nesting_depth que propusiste dentro del plugin de Details integrado, utilizando 0 para anidación ilimitada a fin de preservar el comportamiento existente. La implementación inicial está escrita, pero sus pruebas de integración aún están en curso.

La corrección de rendimiento aborda el problema de conversión de Markdown en el servidor; el límite configurable proporcionaría una salvaguarda adicional, especialmente para el rendimiento del lado del navegador.

Agradecería comentarios sobre la configuración propuesta y si sería preferible incluirla en el mismo PR o enviarla por separado.

3 Me gusta

¡Gracias por la investigación y la corrección tan rápidas!
Creo que sería mejor separarlas en dos PR, para que la corrección de rendimiento pueda revisarse y fusionarse de forma independiente, sin esperar a la nueva configuración.
También apoyo el límite de profundidad configurable, con 0 como valor predeterminado para mantener la compatibilidad hacia atrás.

1 me gusta

Gracias @scavin. Puedo ver la ventaja de separarlos, aunque ambos cambios abordan el mismo informe base que mencionaste y ya están implementados y probados en CI. Tengo activadas las ediciones del mantenedor en todos mis PR, así que me adapto sin problema a la preferencia del equipo de Discourse, ya sea revisar ambos commits juntos o separarlos.

2 Me gusta

gracias a @scavin por el informe y a @Ethsim2 por la PR :+1: también he actualizado la PR para que sea más ligera y he configurado el anidamiento máximo en 10. De todos modos, no estoy seguro de que alguna vez necesitemos soportar más que eso.

3 Me gusta