Pour bien comprendre le problème soulevé :
Je publie un billet le mardi 04 février à 22 heures 15. A 23 heures, la page d'accueil affiche toujours "Publié : Aujourd'hui à 22h15" ce qui est cohérent. Toutefois à 00h15 (donc le lendemain), l'affichage du libellé ne se faisant pas dynamiquement mais étant stocké à plat en XHTML par le ViewCaching , le libellé demeurera inchangé et donc inexact.
Ma démarche a été de forcer la régénération des caches périodiquement et automatiquement pour les billets et noeuds le nécessitant. En voici le détail. C'est également l'occasion d'aborder la gestion des taches automatisées sur eZ publish.
L'algorithme de la solution à cette problématique est simple et correspond à ce que j'ai décrit en introduction à ce billet :
Voici le script dans sa totalité.
<?php
include_once( 'extension/updatecache/classes/requester.php' );
include_once( 'kernel/classes/ezcontentobjecttreenode.php' );
include_once( 'kernel/classes/ezcontentcachemanager.php' );
include_once( 'lib/ezutils/classes/ezlog.php' );
echo "Regénération des caches";
// Récupérer les noeuds devant être mis à jour
$classFilterArray = array( 'billet' );
$targetTimestamp = time() - (60 * 60 * 24 * 2); // 2 Jours : Libellé "Aujourd'hui" et "Hier"
$galerieNodeNodeID = 8723;
//// Récupèrer les *billets* publiés entre now() et now() - 2days
$nodes =& eZContentObjectTreeNode::subTree( array( 'ClassFilterArray' => $classFilterArray ,
'AttributeFilter' => array( array( 'modified' , '>' , $targetTimestamp ) ),
'ClassFilterType' => 'include',
'Depth' => 0,
'SortBy' => array( 'published', false ) ), 2 );
//// Egalement le node *Galeries* qui subira le même traitement
$nodes[] = eZContentObjectTreeNode::fetch( $galerieNodeNodeID );
// Vider le -ViewCache- et récupérer les -url_alias-
// On ne regénère pas le cache dans la même boucle
$urlsToRegenerate = array();
$siteINI = eZINI::instance();
$siteURL = $siteURL->variable( 'SiteSettings' , 'SiteURL' );
foreach ( $nodes as $node )
{
if( is_object( $node ) )
{
eZContentCacheManager::clearContentCacheIfNeeded( $node->attribute( 'contentobject_id' ) );
$fullUrl = 'http://' . $siteURL . '/' . $node->attribute( 'url_alias' );
$urlsToRegenerate[] = $fullUrl;
}
}
// Regénération des caches
foreach( $urlsToRegenerate as $url )
{
echo "Regénération de : " . $url. "\n";
eZlog::write( $url , "ezviewcacheupdater.log" );
Requester::doRequest( $url );
}
?>
Il n'y a ici rien de particulier. Nous utilisons simplement comme il se devrait l'API d'eZpublish.
Pour information, les echo dans le code sont utilisés pour suivre l'exécution du script lorsqu'il est lancé manuellement. Lorsque notre script sera intégré à la crontab du serveur, nous redirigerons l'ensemble des sorties du script vers un fichier de log.
Dans un premier temps, nous récuperons les billets publiés entre aujourd'hui et avant-hier. Ce fetch englobe ainsi les éventuels billets ayant pour libellé "publié aujourd'hui" ou "publié hier".
// Récupérer les noeuds devant être mis à jour
$classFilterArray = array( 'billet' );
$targetTimestamp = time() - (60 * 60 * 24 * 2); // 2 Jours : Libellé "Aujourd'hui" et "Hier"
$galerieNodeNodeID = 8723;
//// Récupèrer les *billets* publiés entre now() et now() - 2days
$nodes =& eZContentObjectTreeNode::subTree( array( 'ClassFilterArray' => $classFilterArray ,
'AttributeFilter' => array( array( 'published' , '>' , $targetTimestamp ) ),
'ClassFilterType' => 'include',
'Depth' => 0,
'SortBy' => array( 'published', false ) ), 2 );
La rubrique galeries s'appuyant sur les mêmes routines est ajoutée au tableau de nodes récupérés précédemment :
//// Egalement le node *Galeries* qui subira le même traitement
$nodes[] = eZContentObjectTreeNode::fetch( $galerieNodeNodeID );
Puis on réinitialise les caches. On génére également un tableau d'URLs absolues que l'on cherchera à regénérer en suite :
// Vider le -ViewCache- et récupérer les -url_alias-
// On ne regénère pas le cache dans la même boucle
$urlsToRegenerate = array();
$siteINI = eZINI::instance();
$siteURL = $siteURL->variable( 'SiteSettings' , 'SiteURL' );
foreach ( $nodes as $node )
{
if( is_object( $node ) )
{
eZContentCacheManager::clearContentCacheIfNeeded( $node->attribute( 'contentobject_id' ) );
$fullUrl = 'http://' . $siteURL . '/' . $node->attribute( 'url_alias' );
$urlsToRegenerate[] = $fullUrl;
}
}
Et enfin, on regénére les caches. Pour ce faire, on simule la visite des noeuds par l'envoi de requêtes http. C'est ce que fait la classe Requester en s'appuyant sur la librairie Curl.
// Regénération des caches
foreach( $urlsToRegenerate as $url )
{
echo "Regénération de : " . $url. "\n";
eZlog::write( $url , "ezviewcacheupdater.log" );
Requester::doRequest( $url );
}
Notre script est fin prêt. Il faut maintenant indiqué au serveur qu'il doit exécuter périodiquement ce code. C'est là qu'interviennent les cronjobs et la crontab (OS Linux). Avant celà, nous allons vérifier le bon fonctionnement du script.
Il convient tout d'abord d'apporter quelques réglages supplémentaires à l'extension : en effet, il est nécessaire de déclarer notre script comme cronjob. Pour ce faire, on rajoutera ces lignes dans notre fichier cronjob.ini.append.php :
<?php /* #?ini charset="iso-8859-1"
[CronjobSettings]
ExtensionDirectories[]=ezviewcacheupdater
[CronjobPart-updateviewcache]
Scripts[]
Scripts[]=updateviewcache.php
*/ ?>
A ce stade pour vérifier le bon fonctionnement du script, il est possible de le lancer manuellement. Rappelons que notre objectif est d'automatiser son exécution à heure fixe. On lancera donc en ligne de commande, après s'être placé à la racine de notre instance d'eZpublish :
php runcronjobs.php updateviewcache
La sortie standard devrait afficher Regénération des caches, signe que tout fonctionne correctement.
Pour plus d'informations sur les crons job et l'utilisation de la crontab sous Linux, je vous renvoie vers l'article de Wikipedia traitant le sujet.
La principale question qu'il faut se poser lors de la mise en place d'un cron job est à quelle fréquence et quand doit tourner mon script ? Dans notre cas, il apparait clair que le script doit s'exécuter au début de chaque nouvelle journée, c'est à dire aux alentours de 00h00. Nous réglerons donc la fréquence d'exécution comme suit :
1 0,1 * * * cd $EZPUBLISHROOT && $PHP runcronjobs.php updateviewcache -q > updateviewcache.log
La partie gauche du script définit la fréquence d'exécution du script. Elle se résume par : à 00h01 et à 01h01 tous les jours exécuter...
On préférera planifier 2 exécutions du script afin de pallier à une éventuelle indisponibilité du serveur.
On pourra s'assurer du bon fonctionnement du cron job en inspectant les fichiers de log le lendemain.
Trackbacks - URL : http://www.starnab.com/trackback/id/233
Pas de trackback sur ce billet. URL : http://www.starnab.com/trackback/id/233
Réactions (5 commentaires)
« Lancer un cronjob »
Salut
# posté par elmoustamid [Guest] le : 21/05/07 à 16h56mon pb est le suivant, je travaille sur EzPublish 3.9 sous windows, j'ai parametré un workflow, pr permettre aux notices validées d'etre publiées, j'ai lu que je dois lancer un cronjobs, j'ai executé celui nomme workflow.php qui se trouve dans le dossier cronjobs, il m'affiche lors de l'execution l'erreur suivante
"PHP Notice: Undefined variable: isQuiet in D:\EZ\Apache2\htdocs\abhatoo\cronjo
bs\workflow.php on line 55
PHP Fatal error: Call to a member function on a non-object in D:\EZ\Apache2\htd
ocs\abhatoo\cronjobs\workflow.php on line 56"
Je n sais pa ce que je dois faire
Merci d'avance
« runcronjobs.php ? php-cli ? »
Bonjour,
# posté par Nabil le : 21/05/07 à 17h18Je vais tenter d'être exhaustif et de procéder dans l'ordre. :)
0. Tu dois tout d'abord avoir php-cli d'installé sur ton environnement.
1. Lances tu bien le script en ligne de commande (et non par ton navigateur) ?
2. De quelle manière lances-tu le workflow en question ? Passes-tu bien par php runcronjobs.php en te plaçant à la racine d'eZ publish ?
3. Précises tu bien le cronjob-part en l'occurence "frequent" ?
Si je prends mon instance de StarNab.com en local par exemple, pour lancer le cron, mon prompt devrait ressembler à quelque chose comme :
C:\Program Files\EasyPHP1-8\www\starnab.com\ezpublish>php runcronjobs.php frequent
Ceci devrait suffire à lancer le cronjob correctement.
« Pourquoi faire simple... »
Pourquoi faire simple...
# posté par olivier [Guest] le : 28/09/07 à 12h07au lieu de mettre "aujourd'hui" ou "hier", "il y a 2 jours" , si tu met la date de publication (..|i10n('date')), le problème ne se présente plus et ça evite de charger la becanne en recalculant periodiquemment le view_content.
++
Et tu penses sincèrement que je n'ai pas songé à cette alternative ? ;)
# posté par Nabil le : 28/09/07 à 12h22"Hier", "Aujourd'hui" seront toujours plus explicites qu'une date.
D'autre part, ce n'est pas la regénération de 3 voir 4 pages à 1 heure du matin qui mettra à mal ma Dédibox.
« qiwyPZNFkLAfqscLI »
93AhZk gfb07yvt9d6t94wbtx63bgq7d
# posté par krissy [Guest] le : 23/07/08 à 09h29...La parole est à vous