2012-09-11 3 views
0

J'ai une action de contrôleur assez lente, qui fait un peu de raport ici et là. J'ai seulement besoin de rafraichir les données tous les quelques jours, donc ce n'était pas évident de mettre en cache le résultat. Le problème est, que l'action prend quelques minutes entières à compléter et je ne suis pas sûr que ce soit le moyen le plus optimal pour expirer les anciennes données et les remplacer par les nouvelles.Quelle est la manière la plus optimale de régénérer le cache statique avec Ruby on Rails?

Maintenant, le problème avec une simple expiration/requête générique est que ces données ne sont pas disponibles pendant quelques minutes (moment où l'action est en cours).

Existe-t-il un moyen raisonnable de surmonter cet écart en utilisant uniquement des mécanismes de cache statiques dans Rails? Ou devrais-je simplement reconstruire le tout d'une manière différente?

Répondre

3

Rails dispose d'un moyen intégré d'utiliser les caches obsolètes pendant un peu plus longtemps lorsqu'il expire pendant la régénération de la nouvelle valeur de cache. C'est le paramètre :race_condition_ttl utilisé en conjonction avec :expires_in, comme décrit dans le Rails Guides on Caching.

Avec Rails Fragment en cache la syntaxe doit être:

<% cache 'my_awesome_cache_key', :expires_in => 12.hours.to_i, :race_condition_ttl => 12.hours.to_i %> 
    # This block will be cached 
<% end %> 

Résultats:

  • 1) Première requête: Cache est vide, si le bloc sera exécuté et les résultats écrit pour mettre en cache
  • 2) Toutes les demandes entre les prochaines 24 heures: Seront servis directement à partir du cache (qui est frais)
  • 3a) Première demande après 24 heures mais dans la période de grâce sera servi à partir du cache alors légèrement vicié; le cache sera régénéré en arrière-plan: le bloc est exécuté et écrit dans le cache dès qu'il est terminé
  • 3b) Première demande après 24 heures mais en dehors du délai de grâce sera traité comme 1), c'est à dire non servi directement mais le bloc sera exécuté, le cache sera écrit et la demande sera servie.

race_condition_ttl a été introduit pour éviter de multiples processus de régénération d'un cache simultaneuosly, qui résulterait dans tous les processus de lecture des données de la db à la fois, etc. sur une ressource très demandée, mais je pense qu'il devrait bien fonctionner pour votre situation.

Comment choisir le calendrier pour :expires_in et :race_condition_ttl est votre choix alors, je suggérerais de le calculer comme ceci: expires_in + race_condition = expires_in_that_you_would_usually_set. De cette façon, le cache est régénéré plus souvent mais aussi plus frais, surtout si l'action/vue n'est pas rendue aussi souvent.

+0

Avez-vous une idée de ce qui se passe si le contenu est expiré manuellement, c'est-à-dire: expire_page: action => ...? La page sera-t-elle toujours servie à partir du cache (jusqu'à ce que course_condition_ttl soit atteint)? – mdrozdziel

+0

Il ne devrait pas y avoir de différence entre l'expiration manuelle et l'expiration temporelle. Tant que la clé du cache reste la même et que la requête est dans le 'race_condition_ttl', je suppose que cela devrait fonctionner comme prévu. –

+1

Les méthodes '.to_i' ne sont pas obligatoires pour' 12.hours' car cela renvoie déjà 'Fixnum'. – Tom

Questions connexes