ActiveRecord counter_cache donnant comte rassis avec petit bijou multi_db
-
20-09-2019 - |
Question
Je suis en utilisant la gemme multi-db avec la réplication Slony-I sur PostgreSQL dans une application Rails. Cela fonctionne parfaitement la plupart du temps, mais il y a un peu de retard de réplication dans certains cas. L'un des cas implique un counter_cache ActiveRecord.
Pour plus de clarté, on suppose les deux modèles suivants:
class Post < ActiveRecord::Base
has_many :comments
...
end
class Comment < ActiveRecord::Base
belongs_to :post, :counter_cache => true, :touch => true
...
end
Après la création d'un commentaire, RJS est appelé à mettre à jour les commentaires compter sur:
@comment.post.comments_count
Avec multi-db désactivé (ou l'entrée de la base de données esclave pointant le maître db), cela fonctionne très bien. Alors, j'ai essayé quelque chose comme ceci:
ActiveRecord::Base.connection_proxy.with_master do
post=@comment.post
count=post.comments_count
end
Cela donne encore un résultat rassis. Comme le fait de réglage:
config.cache_classes = false
Il ressemble à l'appel à with_master
ne fonctionne pas. Des conseils sur la façon de déterminer quelle base de données multi-db utilise? Ou, alternativement, sur la façon de traiter ces questions?
La solution
Dans mon expérience, le plus loin que vous obtenez de Rails « mainstream » des cas d'utilisation ou plus plugins pile, moins vous pouvez compter sur des fonctionnalités avancées pour travailler ensemble. Cela est particulièrement vrai avec la magie ActiveRecord.
S'il est important que votre nombre de commentaires rester à jour, faire explicitement. Débarrassez-vous des counter_cache et mettre en œuvre after_create
et callbacks after_destroy
dans votre modèle de commentaire qui augmenter et diminuer le champ de comptage dans votre modèle Post. (Ou, peut-être plus fiable, les mettre au compte recalculé pour ce champ.) Il semble moins lisse, mais il est peu probable à l'échec dans un ensemble de dépendances raisonnable.
Autres conseils
Je ne sais pas si elle est la solution que vous recherchez, mais j'utiliser masochisme pour ma réplication DB et la fonctionnalité de counter_cache
fonctionne très bien. donc peut-être le problème est dans la pierre précieuse et vous devez déposer un billet.