19-08-2010, 03:26 PM
(Modification du message : 19-08-2010, 03:28 PM par Sephi-Chan.)
Tout comme Zeppelin, la solution la plus simple à mes yeux — et au regard des questions que j'ai posé au début — était d'avoir une colonne points incrémentée au fil des actions. C'est rapide et simple à trier.
Si tu optes pour une solution plus compliquée (en terme de charge serveur et/ou d'algorithme), peu importe.
La seule chose vraiment important, c'est la façon dont tu gères le cache.
Pour ça tu dois décider si tu le fais du côté du modèle (tout ce qui produit et trie le tableau que tu vas afficher) ou de la vue (l'affichage de ton tableau sous forme de HTML). Chaque côté a ses avantages.
Voici un exemple (qui n'utilise rien d'avancé, tout le monde peut comprendre) :
Prenons un scénario simple :
Si une telle erreur te gêne, il est alors plus pertinent de cacher la collection obtenue par le classement. Cela peut se faire comme ceci :
Et là on a le résultat escompté et toujours exact, mais on "perd" le temps de génération du tableau, ce qui peut-être gênant quand la structure est conséquente (par exemple si on inclut dans le HTML plein de données à afficher au survol).
Il faut donc bien réfléchir à la façon dont tu gères ton cache. C'est bien plus important que de trouver une façon efficace de calculer ton classement puisqu'aussi optimisé soit ton algorithme, à partir du moment où il est appelé plusieurs fois (et ce sera forcément le cas), tu perdras un temps monstrueux à le recalculer par rapport à sa lecture depuis un cache.
Bien sûr, plus longtemps dure le cache, plus tu y gagnes, mais tu ne peux pas y perdre : même s'il expire chaque minute, il suffit que 2 personnes le consultent en 1 minute pour que tu le rentabilises, ça arrivera forcément, alors imagine avec une durée de vie de 30 minutes (par exemple).
Sephi-Chan
Si tu optes pour une solution plus compliquée (en terme de charge serveur et/ou d'algorithme), peu importe.
La seule chose vraiment important, c'est la façon dont tu gères le cache.
Pour ça tu dois décider si tu le fais du côté du modèle (tout ce qui produit et trie le tableau que tu vas afficher) ou de la vue (l'affichage de ton tableau sous forme de HTML). Chaque côté a ses avantages.
Voici un exemple (qui n'utilise rien d'avancé, tout le monde peut comprendre) :
# Côté contrôleur.
# Notons qu'ActiveRecord n'effectue la requête que quand on commence à itérer sur la collection.
# La requête sera effectuée au maximum une fois par demi-heure et par page.
@players = Player.order('points DESC').paginate(:page => params[:page], :per_page => 30)
# Côté vue (avec Haml).
- cache([ :rankings, params[:page] ], :expires_in => 30.minutes) do
%table
%tr
%th Nom
%th Points
- @players.each do |player|
%tr
%td= player.name
%td= player.points
Prenons un scénario simple :
- - Personne n'a encore consulté le classement depuis l'expiration des caches ;
- À 13h30, un visiteur consulte la page 1 du classement. La page ne sera pas recalculée avant 14h00 ;
- À 13h40, le 31ème joueur du classement (AAA) dépasse le 30ème (BBB, qui se retrouve 31ème). Le cache de la page 1 affiche donc une erreur : BBB n'est plus 30ème ;
- À 13h50, un visiteur consulte la page 2 du classement : le joueur BBB est la premier de la page (puisqu'il est 31ème), mais il est toujours marqué comme était le 30ème d'après la page 1 qui n'expirera que dans 10 minutes ;
Si une telle erreur te gêne, il est alors plus pertinent de cacher la collection obtenue par le classement. Cela peut se faire comme ceci :
# Côté contrôleur.
# Ici, @players vaut le contenu du cache s'il existe, sinon le contenu du bloc est évalué pour remplir le cache.
@players = cache.fetch([ :rankings ], :expires_in => 30.minutes) do
Player.order('points DESC')
end
@players = @players.paginate(:page => params[:page], :per_page => 30)
# Côté vue (avec Haml).
%table
%tr
%th Nom
%th Points
- @players.each do |player|
%tr
%td= player.name
%td= player.points
Et là on a le résultat escompté et toujours exact, mais on "perd" le temps de génération du tableau, ce qui peut-être gênant quand la structure est conséquente (par exemple si on inclut dans le HTML plein de données à afficher au survol).
Il faut donc bien réfléchir à la façon dont tu gères ton cache. C'est bien plus important que de trouver une façon efficace de calculer ton classement puisqu'aussi optimisé soit ton algorithme, à partir du moment où il est appelé plusieurs fois (et ce sera forcément le cas), tu perdras un temps monstrueux à le recalculer par rapport à sa lecture depuis un cache.
Bien sûr, plus longtemps dure le cache, plus tu y gagnes, mais tu ne peux pas y perdre : même s'il expire chaque minute, il suffit que 2 personnes le consultent en 1 minute pour que tu le rentabilises, ça arrivera forcément, alors imagine avec une durée de vie de 30 minutes (par exemple).
Sephi-Chan