Ambiente
-
Versão do WP-Discourse: 2.5.7
-
Versão do Discourse: 3.5.0.beta5-dev
-
Versão do WordPress: 6.9
-
Hospedagem: WP Engine (WordPress multisite)
-
Instância do Discourse: Auto-hospedada / Hospedagem do Discourse (forum.avweb.com)
Resumo
Publicações publicadas a partir do WordPress criam tópicos no Discourse com sucesso, mas discourse_permalink é armazenado como uma string vazia no meta da publicação. Isso faz com que todas as sincronizações de comentários subsequentes falhem silenciosamente, pois sync_comments() em discourse-comment.php é interrompido antecipadamente quando o permalink está vazio. O ID do tópico do Discourse e a flag de sincronização do webhook são gravados corretamente — apenas o permalink está faltando.
Identificamos 174 publicações afetadas em um único site em nossa rede multisite. O problema parece ter começado por volta de meados de dezembro de 2025.
Passos para Reproduzir
-
Publique uma postagem do WordPress configurada para criar um tópico no Discourse
-
O tópico é criado com sucesso no Discourse
-
discourse_topic_idé salvo no meta da publicação ✓ -
wpdc_sync_post_commentsé definido como1(o webhook dispara corretamente) ✓ -
discourse_permalinké salvo como uma string vazia ✗ -
discourse_comments_rawnunca é gravado (a sincronização nunca é concluída)
Comportamento Esperado
discourse_permalink deve conter o URL completo do tópico do Discourse (ex: The China Chickens Come Home - AVweb - News Discussion - AVweb.com Discussion) após a criação bem-sucedida do tópico.
Comportamento Atual
discourse_permalink existe como uma chave meta, mas seu valor está vazio. Cada chamada subsequente para sync_comments() atinge esta verificação na linha 209 de lib/discourse-comment.php e retorna antecipadamente:
if ( ! $discourse_permalink ) {
return 0;
}
Como a sincronização nunca é concluída, discourse_last_sync nunca é gravado, então o plugin tenta novamente a cada carregamento de página — e falha todas as vezes.
Diagnóstico
Rastreamos o problema através do seguinte caminho de código:
-
DiscourseCommentFormatter::format()chamado_action('wpdc_sync_discourse_comments')que acionaDiscourseComment::sync_comments() -
sync_comments()verificadiscourse_permalink— encontra-o vazio, retorna 0 -
format()então verificadiscourse_comments_rawno custom da publicação — encontra-o ausente, retornabad_response_html() -
Comentários nunca são exibidos para a publicação afetada
O fluxo de criação de tópico está gravando discourse_topic_id, mas falhando em persistir o permalink. Conseguimos reconstruir os permalinks corretos consultando a API do Discourse em /t/{topic_id}.json e gravando-os de volta no meta da publicação, o que resolveu a sincronização para todas as 174 publicações.
Solução Alternativa (Workaround)
Escrevemos um script de reparo WP-CLI que:
-
Encontra publicações onde
wpdc_sync_post_comments = 1, masdiscourse_comments_rawestá ausente -
Busca o slug do tópico em
/t/{topic_id}.json -
Reconstrói e salva o permalink
-
Busca e salva comentários de
/t/{slug}/{topic_id}/wordpress.json
Estamos executando isso em um cron agendado como uma medida paliativa.
Problemas Adicionais Encontrados Durante a Investigação
1. Bloqueio Global do MySQL Causa Falhas Silenciosas de Sincronização
Arquivo: lib/discourse-comment.php, linha 176
$got_lock = $wpdb->get_row( "SELECT GET_LOCK( 'discourse_lock', 0 ) got_it" );
sync_comments() usa um único bloqueio MySQL global (discourse_lock) compartilhado entre todas as publicações em toda a instalação. O tempo limite é 0 (não bloqueante), então se alguma publicação estiver sincronizando no momento, todas as outras publicações silenciosamente ignoram sua sincronização — sem registro, sem nova tentativa.
Em um site de alto volume que publica várias postagens por dia, isso cria uma condição de corrida onde as publicações consistentemente perdem o bloqueio e nunca sincronizam. Combinado com o período de sincronização de 10 minutos, uma publicação pode ficar permanentemente presa se perder o bloqueio em suas primeiras tentativas e, em seguida, o problema do permalink vazio impedir sincronizações futuras.
Correção sugerida: Usar um bloqueio por publicação:
$got_lock = $wpdb->get_row( "SELECT GET_LOCK( 'discourse_lock_{$post_id}', 0 ) got_it" );
Com o correspondente liberação:
$wpdb->get_results( "SELECT RELEASE_LOCK( 'discourse_lock_{$post_id}' )" );
2. Dupla Codificação de discourse_comments_raw
Arquivo: lib/discourse-comment.php, linha 222
update_post_meta( $post_id, 'discourse_comments_raw', esc_sql( $raw_body ) );
update_post_meta() usa $wpdb->prepare() internamente, então envolver o valor em esc_sql() causa dupla codificação. Ao longo de vários ciclos de sincronização, as aspas no corpo JSON se acumulam em caracteres de escape (\\\" → \\\\\\\" → \\\\\\\\\\\\\\\") até que o JSON se torne impossível de analisar.
Correção sugerida:
update_post_meta( $post_id, 'discourse_comments_raw', $raw_body );
Impacto
Esses problemas se acumulam: o permalink vazio impede a sincronização inicial, o bloqueio global impede a recuperação e a dupla codificação pode corromper dados para publicações que conseguem sincronizar. Em nossa instalação, 174 publicações (aproximadamente 2 meses de conteúdo) foram afetadas antes de identificarmos a causa raiz.