Ambiente
-
Versione WP-Discourse: 2.5.7
-
Versione Discourse: 3.5.0.beta5-dev
-
Versione WordPress: 6.9
-
Hosting: WP Engine (WordPress multisite)
-
Istanza Discourse: Self-hosted / Hosting Discourse (forum.avweb.com)
Riepilogo
I post pubblicati da WordPress creano con successo argomenti su Discourse, ma discourse_permalink viene memorizzato come stringa vuota nei metadati del post. Ciò fa sì che tutte le successive sincronizzazioni dei commenti falliscano silenziosamente, poiché sync_comments() in discourse-comment.php termina anticipatamente quando il permalink è vuoto. L’ID dell’argomento Discourse e il flag di sincronizzazione webhook vengono scritti correttamente: manca solo il permalink.
Abbiamo identificato 174 post interessati su un singolo sito nella nostra rete multisito. Il problema sembra essere iniziato intorno alla metà di dicembre 2025.
Passaggi per Riprodurre
-
Pubblicare un post WordPress configurato per creare un argomento Discourse
-
L’argomento viene creato con successo su Discourse
-
discourse_topic_idviene salvato nei metadati del post ✓ -
wpdc_sync_post_commentsè impostato su1(il webhook viene attivato correttamente) ✓ -
discourse_permalinkviene salvato come stringa vuota ✗ -
discourse_comments_rawnon viene mai scritto (la sincronizzazione non viene mai completata)
Comportamento Atteso
discourse_permalink dovrebbe contenere l’URL completo dell’argomento Discourse (es. The China Chickens Come Home - AVweb - News Discussion - AVweb.com Discussion) dopo la creazione riuscita dell’argomento.
Comportamento Effettivo
discourse_permalink esiste come chiave meta ma il suo valore è vuoto. Ogni chiamata successiva a sync_comments() raggiunge questa guardia alla riga 209 di lib/discourse-comment.php e restituisce anticipatamente:
if ( ! $discourse_permalink ) {
return 0;
}
Poiché la sincronizzazione non viene mai completata, discourse_last_sync non viene mai scritto, quindi il plugin tenta di nuovo ad ogni caricamento di pagina, fallendo ogni volta.
Diagnosi
Abbiamo tracciato il problema attraverso il seguente percorso di codice:
-
DiscourseCommentFormatter::format()chiamado_action('wpdc_sync_discourse_comments')che attivaDiscourseComment::sync_comments() -
sync_comments()controlladiscourse_permalink— lo trova vuoto, restituisce 0 -
format()quindi controlladiscourse_comments_rawnei metadati del post — lo trova mancante, restituiscebad_response_html() -
I commenti non vengono mai visualizzati per il post interessato
Il flusso di creazione dell’argomento sta scrivendo discourse_topic_id ma non riesce a persistere il permalink. Siamo stati in grado di ricostruire i permalink corretti interrogando l’API di Discourse a /t/{topic_id}.json e riscrivendoli nei metadati del post, il che ha risolto la sincronizzazione per tutti i 174 post.
Soluzione Temporanea
Abbiamo scritto uno script di riparazione WP-CLI che:
-
Trova i post in cui
wpdc_sync_post_comments = 1madiscourse_comments_rawè mancante -
Recupera lo slug dell’argomento da
/t/{topic_id}.json -
Ricostruisce e salva il permalink
-
Recupera e salva i commenti da
/t/{slug}/{topic_id}/wordpress.json
Lo stiamo eseguendo su un cron programmato come misura provvisoria.
Problemi Aggiuntivi Riscontrati Durante l’Indagine
1. Blocco MySQL Globale Causa Fallimenti Silenziosi della Sincronizzazione
File: lib/discourse-comment.php, riga 176
$got_lock = $wpdb->get_row( "SELECT GET_LOCK( 'discourse_lock', 0 ) got_it" );
sync_comments() utilizza un singolo blocco MySQL globale (discourse_lock) condiviso tra tutti i post dell’intera installazione. Il timeout è 0 (non bloccante), quindi se un post è attualmente in sincronizzazione, tutti gli altri post saltano silenziosamente la loro sincronizzazione — nessun log, nessun tentativo di ripetizione.
Su un sito ad alto volume che pubblica più post al giorno, ciò crea una condizione di gara in cui i post perdono costantemente il blocco e non vengono mai sincronizzati. Combinato con il periodo di sincronizzazione di 10 minuti, un post può rimanere bloccato permanentemente se perde il blocco ai primi tentativi e poi il problema del permalink vuoto impedisce le sincronizzazioni future.
Correzione suggerita: Utilizzare un blocco per post:
$got_lock = $wpdb->get_row( "SELECT GET_LOCK( 'discourse_lock_{$post_id}', 0 ) got_it" );
Con il rilascio corrispondente:
$wpdb->get_results( "SELECT RELEASE_LOCK( 'discourse_lock_{$post_id}' )" );
2. Doppia Codifica di discourse_comments_raw
File: lib/discourse-comment.php, riga 222
update_post_meta( $post_id, 'discourse_comments_raw', esc_sql( $raw_body ) );
update_post_meta() utilizza $wpdb->prepare() internamente, quindi racchiudere il valore in esc_sql() causa una doppia codifica. Nel corso di più cicli di sincronizzazione, le virgolette nel corpo JSON accumulano caratteri di escape (\\" → \\\\\\" → \\\\\\\\\\\\\\" ) fino a quando il JSON diventa non analizzabile.
Correzione suggerita:
update_post_meta( $post_id, 'discourse_comments_raw', $raw_body );
Impatto
Questi problemi si sommano: il permalink vuoto impedisce la sincronizzazione iniziale, il blocco globale impedisce il ripristino e la doppia codifica può corrompere i dati per i post che riescono a sincronizzarsi. Sulla nostra installazione, 174 post (circa 2 mesi di contenuti) sono stati interessati prima che identificassimo la causa principale.