Prioridade/Severidade: Raro, mas crítico
O site fica inutilizável por até 30 minutos após erros transitórios no banco de dados. As páginas não carregam corretamente devido a configurações de cliente ausentes que causam erros de JavaScript.
Plataforma:
- Afeta: Todas as instalações do Discourse
- Observado em: Ambientes de produção que experimentam problemas transitórios de conectividade com o banco de dados
Descrição
Resultado Atual
Quando ocorre um erro transitório no banco de dados (timeout de conexão, esgotamento do pool, falha de rede), o erro é armazenado em cache por 30 minutos. Durante esse tempo:
- O site não carrega corretamente - as páginas aparecem quebradas ou não funcionais
- Ocorrem erros de JavaScript no lado do cliente devido a configurações ausentes/inválidas
- Cada solicitação registra “Nil client_settings_json from the cache for ‘client_settings_json\[git_version\]’”
- Configurações de cliente vazias são retornadas ao navegador
- Isso continua mesmo após o banco de dados ter se recuperado totalmente
Resultado Esperado
Quando ocorre um erro transitório no banco de dados, o sistema não deve armazenar o erro em cache. Assim que o banco de dados se recuperar, a próxima solicitação deve buscar e armazenar em cache com sucesso as configurações do cliente, e o site deve retomar a operação normal imediatamente.
Passos para Reproduzir
- Inicie uma instância do Discourse com as configurações do cliente configuradas
- Simule um problema de conectividade com o banco de dados (por exemplo, esgote o pool de conexões, introduza um atraso na rede ou bloqueie temporariamente a porta 5432)
- Faça uma solicitação que acione SiteSetting.client_settings_json (qualquer carregamento de página fará isso)
- Observe o erro: “Error while generating client_settings_json_uncached: [database error]”
- As páginas não são renderizadas corretamente, o console JavaScript mostra erros relacionados a configurações ausentes
- Restaure a conectividade do banco de dados
- Faça solicitações adicionais nos próximos 30 minutos. Continue vendo erros “Nil client_settings_json from the cache” apesar do banco de dados estar saudável
- Após 30 minutos, o cache expira e o site finalmente se recupera
Impacto no Usuário
O site fica efetivamente inativo durante este período:
- As páginas não são renderizadas corretamente
- Aplicações JavaScript falham ao inicializar devido à falta de configuração
Isso transforma um soluço de banco de dados de 1 segundo em uma interrupção de 30 minutos.
Causa Raiz
Em lib/site_setting_extension.rb, o método client_settings_json_uncached captura exceções e retorna nil. Esse nil é armazenado em cache por 30 minutos, quebrando o site.
Correção Proposta
Uma pull request foi submetida para corrigir este problema. A correção requer uma alteração simples para relançar a exceção em vez de retornar nil.
Por que funciona:
- Relançar a exceção impede que Discourse.cache.fetch armazene o erro em cache
- O método externo client_settings_json já possui tratamento de exceção adequado que retorna “” (string vazia) sem armazená-lo em cache
- O site pode continuar funcionando durante problemas no banco de dados (embora degradado)
- O site se recupera automaticamente na próxima solicitação assim que o banco de dados estiver saudável
- A correção garante que erros transitórios no banco de dados não causem interrupções de 30 minutos.
Impacto
Este bug afeta todas as instalações do Discourse que experimentam problemas transitórios no banco de dados:
- Esgotamento do pool de conexões durante picos de tráfego
- Falhas de rede entre o aplicativo e o banco de dados
- Cenários de failover do banco de dados (por exemplo, troca de primário/réplica)
- Contenção de bloqueio na tabela site_settings
- Timeouts de consulta devido a consultas lentas
Severidade: Qualquer um desses problemas comuns e transitórios faz com que todo o site fique inutilizável por 30 minutos, mesmo que o problema subjacente se resolva em segundos.
Solução Alternativa
Se você estiver enfrentando este problema agora, pode limpar manualmente o cache para restaurar o serviço:
No console Rails
Discourse.cache.delete(SiteSettingExtension.client_settings_cache_key)