En prime : CacheLab étend #CACHE et INCLURE

En plus des actions ciblées sur les caches exposées dans les autres articles, CacheLab étend les balises #CACHE et #INCLURE ou <INCLURE> de manière à implémenter :

  • L’argument d’url var_cache, utile pour le debuging et la maintenance
  • Une extension de la balise #CACHE
  • La possibilité de spécifier une durée de cache de manière dynamique via un argument duree-cache de leurs inclusions.
  • Des tests et assertions à utiliser dans vos squelettes, portant sur le sessionnement du cache.
  • Une transformation du cache sur mesure aprés son calcul

Ces fonctionnalités sont utilisables en complément de l’API fournie par CacheLab, ou sans que cette API soit utilisée. Sauf exception, elles ne nécessitent pas un cache APC ou APCu sur le serveur. Certaines d’entre elles nécessitent que Memoization soit active, mais ce peut être avec une méthode quelconque, y compris filecache qui est disponible sur tous les hébergements.

On peut donc activer CacheLab uniquement pour bénéficier de var_cache ou de la balise #CACHE étendue, sans que ça impacte le site par ailleurs.

Afficher les infos avec ?var_cache=oui

La variable d’environnement var_cache, lorsqu’elle est présente dans l’url, permet d’afficher des informations sur les caches générés pour chaque noisette incluse dynamiquement dans la page :

L’état de sessionnement (comme avec #CACHE{session log})
Exemple d’un cache non sessionné :

Exemple d’un cache sessionné avec visiteur identifié :

La durée du cache lorsqu’elle a été calculée par une méthode dynamique
Exemple d’un cache de durée dynamique dont la durée calculée est de 1800s :

Remarques :
-  Il est nécessaire de combiner var_cache=oui avec var_mode=recalcul (ou au moins avec var_mode=calcul) pour avoir un maximum d’informations sur les caches. Sans cela, si votre site est normalement et correctement conçu, il n’y a aucun calcul et var_mode=cache n’affiche rien.
-  Les modèles n’ont pas de cache qui leur soit propre. Leurs informations n’apparaissent donc pas avec var_cache.

Loger des éléments du cache avec #CACHE{log}

La balise #CACHE accepte un nouvel argument ’log".
#CACHE{log ...} permet de loger des morceaux du cache, métadonnées et valeur .

Le nom du fichier de cache utilisé pour ces logs est le nom du chemin du squelette, dans lequel les / ont été remplacés par des _, et préfixé par cachelab_

Ces arguments peuvent se combiner à une durée numérique pré-existante :

#CACHE{3600, log} : loge tout le cache, méta et html (et cet exemple spécifie aussi une durée de 3600s pour le cache)

Il est possible de préciser ce qu’on demande de loger :

#CACHE{log lastmodified} : loge l’entrée ’lastmodified’ du cache

#CACHE{log contexte} : loge tout le tableau des variables environnement (#ENV)

#CACHE{log contexte/date_creation} : loge l’entrée ’date_creation’ de l’environnement

Assertions pour vérifier le sessionnement avec #CACHE{session}

La bonne conception d’un squelette dans lequel l’internaute peut s’identifier suppose de parfaitement savoir si un squelette est sessionné ou non pour éviter d’exploser les caches sessionnés.

La méthode session ne change pas le comportement du cache mais permet de vérifier que le squelette se comporte bien comme on l’a conçu, et que ce comportement perdure lors des évolutions futures de ce squelette ou d’autres parties du jeu de squelette.

Assertions

On vérifie que le sessionnement est conforme avec session assert suivi de la valeur de sessionnement attendue. Dans le cas où une assertion n’est pas vérifié, une erreur est logée dans le fichier cachelab_assertsession

Les valeurs possibles du sessionnement sont : oui, oui_anonyme, oui_login, non, anonyme :

-  #CACHE{session assert non} déclare que les emplois de la noisette courante sont non sessionnés
-  #CACHE{session assert oui} déclare que les emplois de la noisette courante sont sessionnés
-  #CACHE{session assert oui_login} déclare que les emplois sont sessionnés avec un internaute identifié
-  #CACHE{session assert anonyme} déclare que les emplois sont non sessionnés ou sans internaute identifié

Ces arguments s’ajoutent à un éventuel argument standard qui vient en premier et qui indique la durée du cache :
-  #CACHE{3600, session assert non} indique une durée du cache de 3600 secondes et demande de vérifier que les emplois sont non-sessionnés.

Aide à la mise au point

La méthode session accepte d’autres arguments utiles le temps d’une mise au point :
-  #CACHE{session assert_echo ...} : fait une assertion et affiche un avertissement à l’écran lorsque la valeur constatée de sessionnement n’est pas conforme à la valeur attendue. C’est une bonne option le temps de la mise au point.
-  #CACHE{session echo} : l’état du sessionnement est affiché à l’écran au moment du calcul du cache
-  #CACHE{session log} : l’état du sessionnement est logé dans le fichier de logs cachelab dédié à ce squelette. Le résultat est similaire à #CACHE{log invalideurs/session}.
-  #CACHE{session insert} : le code qui affiche l’état du sessionnement est inséré à la fin du contenu HTML du cache. Il s’affichera donc chaque fois qu’on affiche ce cache. Rq1 : L’usage de l’argument session insert nécessite Memoization. Rq2 : Cette fonctionnalité est expérimentale et vos retours sont bienvenus.

Filtrage post-calcul d’un cache avec #CACHE{macommande}

Il est possible pour le webmestre de définir des méthodes macommande de filtrages du cache associés à un squelette.

Pour traiter une instruction #CACHE{macommande arg1 arg2}, le webmestre doit définir une fonction cachelab_filtre_macommande. Cette fonction :

  • est appelée après le calcul du cache
  • reçoit 2 arguments :
    - le cache entier (métadonnées et code compilé). Si cet argument est reçu par référence, la fonction peut le modifier et demander de mettre à jour la version mémoizée.
    - le reste de l’argument de #CACHE. Dans l’exemple ce sera arg1 arg2
  • renvoie un booléen :
    - true si l’argument $cache est passé par référence et a été modifié. Cachelab se chargera alors d’actualiser le cache (et pour cela il faut que Memoization soit actif).
    - false sinon.

Le webmestre peut ainsi définir lui même ses filtres à caches. Par exemple #CACHE{1200,bidouille grave} appelle, aprés chaque calcul et enregistrement d’un cache, la fonction cachelab_filtre_bidouille avec 2 arguments : le $cache et l’argument $arg valant ’grave’.

Remarques

-  2 filtres de cache sont livrés d’origine avec le plugin : session et log, décrits plus haut. Leur code peut servir d’exemple pour en coder d’autres.

-  La fonctionnalité #FILTRE de SPIP (usage : #FILTRE{unfiltre}) est différente puisqu’elle porte sur le contenu HTML, alors que les filtres de cache portent sur le cache entier, contenu HTML et métadonnées.

-  Autrement dit, #FILTRE{monfiltre} est au HTML généré par un squelette ce que #CACHE{monfiltre} est au cache complet généré par ce squelette, HTML et métadonnées comprises. Une fonctionnalité identique à la balise #FILTRE pourrait être obtenue par un filtrage sur le cache qui ne s’appliquerait qu’à l’entrée texte du cache.

-  #CACHE ne peut pas recevoir plusieurs arguments de type ’filtre’, mais un seul. On ne peut donc pas combiner un log, un assert et un filtre maison. Si c’est nécessaire, le webmestre devra définir un filtre maison qui combine les filtres désirés de la manière voulue.

Cache de durée dynamique et contextuelle avec #CACHE{duree}

Dans le core, la durée de cache spécifiée par #CACHE sert quand c’est 0, mais quand elle n’est pas nulle, elle sert rarement puisque l’ensemble de tous les caches est invalidé à chaque création ou modification de contenu par un internaute, avant donc l’expiration du cache.

Lorsque Cachelab a permis de supprimer toutes les invalidations globales du site et qu’il ne reste que les invalidations voulues, alors il n’y a pas d’invalidations prématurées, et la durée indiquée pour le cache peut réellement servir. La balise #CACHE se révèle alors parfois insuffisante pour coller aux besoins de certaines noisettes : lorsque la durée du cache doit varier selon les moments et le contexte.

Cela se présente par exemple lorsqu’on veut indiquer l’âge d’un article, depuis « déposé à l’instant » jusqu’à « il y a 2 ans » en passant par « Il y a 15 secondes », « il y a 2h », « hier », « la semaine dernière » ou « il y a 6 mois » etc. Lorsque l’article est tout frais, la noisette doit être très souvent mise à jour (toutes les minutes au début !), alors qu’après 3 mois, on peut se satisfaire d’une indication plus approximative : « il y a 5 mois » (la progression de la durée est visible dans le source. Bref, la durée du cache doit dépendre de l’âge et de la précision voulue. Or la balise #CACHE n’accepte que des valeurs numériques et ne permet pas de faire des calculs pour établir la durée du cache.

Pour permettre cela, on peut spécifier une fonction de calcul de durée dynamique d’un cache pour un squelette :#CACHE{duree methode unenv}

-  methode aprés duree indique quelle méthode sera utilisée pour calculer la durée du cache : c’est la fonction cachelab_duree_methode qui sera appelée. Le webmestre doit la définir de manière à ce qu’elle calcule dynamiquement la durée en fonction d’une des variables d’environnement.

-  unenv est le nom d’une des variables de l’environnement du cache. Souvent, ce sera un champ SQL de l’objet principal affiché par le squelette, avec un format DATE ou DATETIME. Par défaut, c’est date_creation. Cette valeur sera transmise en argument à la fonction cachelab_duree_methode.

Si la valeur renvoyée par cette fonction est null, alors la durée n’est pas modifiée.

Deux méthodes prédéfinies de calcul de durée dynamique sont livrées avec le plugin :

-  progapprox. Elle renvoie une durée de cache progressive : valant 10 secondes lorsque la date_creation date de moins d’une minute, elle augmente progressivement avec l’âge de l’objet affiché, jusqu’à valoir 6 mois pour les objets de plus de 2 ans.

Exemple : #CACHE{1200,duree-progapprox date_publication} : le cache aura une durée progressive approximative calculée par la fonction cachelab_duree_progapprox à partir de la date de publication. La valeur 1200 servira seulement si on désactive le plugin CACHELAB. Si cette méthode de durée progressivene convient pas, il appartient au webmestre de coder la fonction qui implémente la méthode dont il a besoin.

-  jusqueminuit, permet qu’un cache se recalcule chaque nuit après minuit.
#CACHE{duree jusqueminuit}. La fonction est définie ainsi :

/**
 * Calcule une durée de cache sans rafraîchissement jusqu'au lendemain minuit cinq.
 *
 * @param $date_unused : inutilisé
 * @return int : le nombre de secondes restant jusqu'au prochain minuit cinq
 */
function cachelab_duree_jusqueminuit($date_unused) {
    return strtotime('tomorrow') + 300 - time();
}

Constantes de paramétrages

2 constantes permettent de paramétrer les logs :
-  LOG_BALISECACHE_FILTRES : faut-il loger les applications de filtres sur #CACHE ? (vrai par défaut)
-  LOG_BALISECACHE_DUREES_DYNAMIQUES : faut-il loger les applications de durées dynamiques de cache ? (faux par défaut)

Remarques :

-  Entre le code SPIP et l’écran d’un internaute il y a de nombreux autres systèmes de caches que ceux gérés par SPIP, notamment varnish, des proxies et le cache navigateur. Les paramétrages du site doivent prendre correctement en compte tous ces caches pour que l’effet de #CACHE{durée truc} se manifeste comme désiré.
De plus, la noisette ne sera pas recalculée avant d’être requise par un internaute... ce qui peut avoir lieu bien plus tard qu’à minuit 5.

-  Inversement, si l’API de CacheLab n’est pas utilisée pour qu’il ne se produise plus d’invalidation totale des caches, il y a de fortes chances que le cache soit invalidé plusieurs fois dans la journée (voire de très nombreuses fois), ce qui à chaque fois nécessitera le recalcul de cette noisette si elle doit ensuite être affichée. Dans ce cas, l’instruction est moins utile, mais a tout de même l’intérêt de s’assurer que l’affichage de cette noisette soit mis à jour au premier affichage après minuit 5.

Si l’API de CacheLab a été utilisée pour qu’il ne se produise jamais d’invalidation totale du cache, alors cette noisette ne sera jamais recalculée sans raison. Cette instruction est nécessaire pour que l’affichage de cette noisette soit mise à jour, et cela se fera au premier affichage après minuit 5.

-  L’usage de l’argument duree nécessite Memoization.

Inclusion avec argument duree-cache

Lorsqu’on évalue un squelette avec un contexte duree-cache, alors cachelab donne la valeur de cette duree-cache comme durée du cache créé.

Exemple d’inclusion dans une boucle fournissant un id_auteur :

  #SET{duree, 3600}
  [(#SESSION{id_auteur}|={#ID_AUTEUR}|oui) #SET{duree, 60}]
  <INCLURE{fond=scores,duree-cache=#GET{duree},id_auteur}/>

Ainsi, la durée du cache est spécifiée par le contexte incluant, et non pas la noisette inclue.

Tests unitaires

Des tests unitaires ont été définis et peuvent être accédés par la page ?page=cachetest. Cette page est auto-documentée. Les tests vérifient le bon sessionnement des noisettes dans diverses situations : suite d’inclusions dynamiques, suite d’inclusions statiques, suite de modèles, emboîtements d’inclusions dynamiques et statiques.

Les options du menu des tests proposent d’afficher
-  avec recalcul : les assertions s’affichent si jamais un sessionnement n’est pas conforme (les noisettes contiennent un #CACHE{session assert_echo ...}. Une classe cachelab_assert colorie ces affichages en orange.
-  avec recalcul et var_cache : les états de sessionnement de toutes les noisettes s’affichent (sauf les modèles)

Ces tests ont permis notamment de confirmer un bug dans le noyau de SPIP (cf « un cache sessionné contamine les caches non sessionnés suivants ») et de tester l’efficacité et la non-régression du fix proposé.

Voir aussi


-  API CacheLab 1. Action sur des caches ciblés
-  API CacheLab 2. Actions globales par type d’invalidation
-  Compléments CacheLab et todo
-  XRay, un explorateur des caches SPIP
-  Plugin ’macrosession’ : usage optimisé et extension des données de session

Vérifier : un changement dans la révision 24213 de SPIP 3.3 a induit une incompatibilité avec les versions antérieures de Cachelab et réciproquement. Il faut donc un SPIP plus récent pour utiliser les versions récentes de Cachelab.

Discussion

Aucune discussion

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom