Priorité/Gravité : Rare mais critique
Le site devient inutilisable pendant 30 minutes après des erreurs de base de données transitoires. Les pages ne se chargent pas correctement en raison de paramètres client manquants qui provoquent des erreurs JavaScript.
Plateforme :
- Affecte : Toutes les installations Discourse
- Observé dans : Environnements de production connaissant des problèmes de connectivité de base de données transitoires
Description
Résultat actuel
Lorsqu’une erreur de base de données transitoire se produit (délai d’attente de connexion, épuisement du pool, problème réseau), l’erreur est mise en cache pendant 30 minutes. Pendant ce temps :
- Le site ne se charge pas correctement : les pages apparaissent cassées ou non fonctionnelles
- Des erreurs JavaScript côté client se produisent en raison de paramètres manquants/invalides
- Chaque requête enregistre « Nil client_settings_json from the cache for ‘client_settings_json\[git_version\]’ »
- Des paramètres client vides sont renvoyés au navigateur
- Cela continue même après que la base de données a complètement récupéré
Résultat attendu
Lorsqu’une erreur de base de données transitoire se produit, le système ne doit pas mettre l’erreur en cache. Une fois la base de données récupérée, la prochaine requête doit récupérer et mettre en cache avec succès les paramètres client, et le site doit reprendre son fonctionnement normal immédiatement.
Étapes reproductibles
- Démarrer une instance Discourse avec des paramètres client configurés
- Simuler un problème de connectivité de base de données (par exemple, épuiser le pool de connexions, introduire un délai réseau ou bloquer temporairement le port 5432)
- Effectuer une requête qui déclenche
SiteSetting.client_settings_json(n’importe quel chargement de page le fera) - Observer l’erreur : « Error while generating client_settings_json_uncached: \[database error\] »
- Les pages ne se rendent pas correctement, la console JavaScript affiche des erreurs liées à des paramètres manquants
- Restaurer la connectivité de la base de données
- Effectuer des requêtes supplémentaires pendant les 30 minutes suivantes. Continuer à voir des erreurs « Nil client_settings_json from the cache » malgré une base de données saine
- Après 30 minutes, le cache expire et le site récupère enfin
Impact utilisateur
Le site est effectivement en panne pendant cette période :
- Les pages ne se rendent pas correctement
- Les applications JavaScript ne s’initialisent pas en raison d’une configuration manquante
Cela transforme un problème de base de données de 1 seconde en une panne de 30 minutes.
Cause racine
Dans lib/site_setting_extension.rb, la méthode client_settings_json_uncached (discourse/lib/site_setting_extension.rb at main · discourse/discourse · GitHub) intercepte les exceptions et renvoie nil (discourse/lib/site_setting_extension.rb at main · discourse/discourse · GitHub). Ce nil est mis en cache pendant 30 minutes, ce qui casse le site.
Correction proposée
Une pull request a été soumise pour corriger ce problème. La correction nécessite une simple modification pour relancer l’exception au lieu de renvoyer nil.
Pourquoi ça marche :
- Relancer l’exception empêche
Discourse.cache.fetchde mettre l’erreur en cache - La méthode externe
client_settings_jsongère déjà correctement les exceptions, renvoyant une chaîne vide ("") sans la mettre en cache - Le site peut continuer à fonctionner pendant les problèmes de base de données (bien que dégradé)
- Le site récupère automatiquement à la prochaine requête une fois la base de données saine
- La correction garantit que les erreurs de base de données transitoires ne provoquent pas de pannes de 30 minutes.
Impact
Ce bug affecte toutes les installations Discourse rencontrant des problèmes de base de données transitoires :
- Épuisement du pool de connexions lors des pics de trafic
- Problèmes réseau entre l’application et la base de données
- Scénarios de basculement de base de données (par exemple, basculement maître/réplique)
- Contention de verrouillage sur la table
site_settings - Dépassements de délai d’attente des requêtes en raison de requêtes lentes
Gravité : N’importe lequel de ces problèmes courants et transitoires rend le site entier inutilisable pendant 30 minutes, même si le problème sous-jacent se résout en quelques secondes.
Solution de contournement
Si vous rencontrez ce problème actuellement, vous pouvez vider manuellement le cache pour rétablir le service :
Dans la console Rails
Discourse.cache.delete(SiteSettingExtension.client_settings_cache_key)