Aggiungere una profondità di annidamento massima per i dettagli comprimibili

Vorrei suggerire di aggiungere una profondità massima di annidamento per la funzione integrata [details], oppure di introdurre un’impostazione del sito che consenta agli amministratori di configurare questo limite.

Il problema

Recentemente, un utente del mio forum Discourse ha creato un post contenente 24 livelli di sezioni [details] annidate.

Ciò ha causato diversi problemi:

  1. Prestazioni del browser: Gli utenti hanno segnalato che l’espansione di più livelli causava a Firefox di diventare estremamente lento o non reattivo.
  2. Timeout dell’endpoint Markdown: L’accesso all’endpoint .md del topic diventava estremamente lento. Abbiamo osservato richieste che richiedevano 19,8 secondi e 31,1 secondi.
  3. Errori del server: L’endpoint Markdown a volte restituiva una pagina di errore “Oops”. I log di Discourse mostravano anche avvisi di timeout dei worker Pitchfork durante la conversione Markdown.
  4. Possibile esaurimento delle risorse: Poiché i motori di ricerca e i crawler AI richiedono frequentemente gli endpoint .md, un post profondamente annidato potrebbe ripetutamente attivare elaborazioni costose e consumare risorse del server.

Dopo la rimozione del post problematico, l’endpoint Markdown ha restituito HTTP 200 e ha risposto in circa 1,7 secondi.

Il topic interessato era:

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

(La risposta problematica è stata già rimossa.)

Miglioramento suggerito

Credo sarebbe utile:

  • Limitare l’annidamento di [details] a una profondità ragionevole, come 2 o 3 livelli.
  • Aggiungere un’impostazione del sito, come details_max_nesting_depth, che consenta agli amministratori di configurare la profondità massima di annidamento.

Per la compatibilità retroattiva, l’impostazione potrebbe essere illimitata per impostazione predefinita, consentendo agli amministratori di applicare un limite quando necessario.

Se gli utenti superano il limite configurato, Discourse potrebbe rifiutare il post con un chiaro messaggio di validazione.

Soluzione temporanea: un plugin

Ho creato un piccolo plugin che limita l’annidamento di [details] a un massimo di 2 livelli:

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

Il plugin valida i post lato server e rifiuta i post contenenti più di due livelli di sezioni richiudibili annidate.

L’ho testato con successo nel mio ambiente di sviluppo Discourse locale.

Per gli amministratori che riscontrano problemi simili, questo plugin può servire come soluzione temporanea fino a quando non sarà disponibile una soluzione ufficiale.

Credo che un limite configurabile nel plugin Details integrato sarebbe una salvaguardia utile contro l’annidamento accidentale o eccessivo.

2 Mi Piace

Ciao @scavin, grazie per aver segnalato questo problema e per aver fornito i dettagli di riproduzione.

Ho indagato sul rallentamento dell’endpoint Markdown che hai descritto e ho identificato un problema in MarkdownEndpoint::CookedProcessor#replace_details: gli elementi <details> annidati venivano convertiti ripetutamente, causando un’elaborazione esponenziale.

Ho aperto una PR draft upstream con una correzione:

A otto livelli di annidamento, la correzione ha ridotto le conversioni ricorsive da 255 a 8, con un miglioramento delle prestazioni di circa 31 volte nel mio benchmark locale. La PR ha superato i controlli CI di GitHub iniziali.

Sto anche lavorando all’impostazione di sito details_max_nesting_depth da te proposta, all’interno del plugin Details integrato, utilizzando 0 per un’annidamento illimitato al fine di preservare il comportamento esistente. L’implementazione iniziale è stata scritta, ma i test di integrazione sono ancora in corso.

La correzione delle prestazioni risolve il problema di conversione Markdown lato server; il limite configurabile fornirebbe un’ulteriore misura di sicurezza, in particolare per le prestazioni lato browser.

Sarebbe gradito un feedback sull’impostazione proposta e su se sia preferibile includerla nella stessa PR o inviarla separatamente.

1 Mi Piace

Grazie per la rapida indagine e per la correzione!
Penso che sarebbe meglio separarli in due PR, in modo che la correzione delle prestazioni possa essere revisionata e unita in modo indipendente, senza dover aspettare la nuova impostazione.
Sostengo anche il limite di profondità configurabile, con 0 come valore predefinito per la compatibilità all’indietro.