Tâches planifiées avec WordPress

Un blog est avant tout une application interactive. Interactive pour les visiteurs qui voient s’afficher des pages en fonction de leurs requêtes, interactive pour les auteurs/administrateurs, qui peuvent saisir des informations et les gérer.
Certains opérations ne demandent cependant pas d’interactions avec un utilisateur, et nécessitent d’être exécutées périodiquement. Les sauvegardes en sont un excellent exemple: elles n’ont besoin d’aucune intervention humaine, et il est important qu’elles tournent régulièrement.
WordPress dispose de fonctions permettant de déclencher des actions, non pas en fonction de requêtes, mais en utilisant des paramètres temporels.
Nous allons voir comment fonctionnent ces tâches planifiées, la notion de Cron, ainsi que l’API proposé par WordPress sur ce sujet.

Planification de tâches

En informatique, les tâches planifiées sont très souvent associées au terme cron.

Cron

Selon Wikipedia,
cron est le nom d’un programme qui permet aux utilisateurs des systèmes Unix d’exécuter automatiquement des scripts, des commandes ou des logiciels à une date et une heure spécifiées à l’avance, ou selon un cycle défini à l’avance. Le nom est dérivé du grec chronos, signifiant le temps. (Cron. (2009, mars 3). Wikipédia, l’encyclopédie libre. Page consultée le 13 mars, 2009 à partir de http://fr.wikipedia.org/w/index.php?title=Cron&oldid=38585764.)

Pour résumer, un service / processus / démon, consulte régulièrement une table contenant une liste de tâches, et lance leur exécution, en fonction de paramètres de temps incluant soit une heure précise, soit une fréquence, soit les deux.

Les systèmes d’exploitation étant multi-tâches,

  • Ce démon fonctionne en tâche de fond, en parallèle des autres activités du système,
  • Les tâches sont démarrées précisément aux horaires spécifiés
  • et s’exécutent de façon transparente, complètement en parallèle du reste du système.

Les crons et WordPress

La notion de tâches planifiées est d’abord apparue dans WordPress sous la forme d’un plugin appelé WP-Cron.
Puis WordPress, à partir de la version 2.0 a directement intégré les fonctionnalités de ce plugin.

WordPress offre donc la possibilité de déclencher l’exécution de tâches, sans demande explicite d’un utilisateur, ou d’un administrateur. Compte tenu de la nature même de l’application WordPress, il faut être conscient que les fonctions cron n’ont pas le même comportement que celles que proposent un système d’exploitation.

WordPress n’est ni plus ni moins qu’un (gros) script PHP, qui répond à des requêtes HTTP:

  • Certes le serveur Web est capable de répondre à plusieurs requêtes simultanément, mais pour une requête (un visiteur) donnée, l’exécution est mono-tâche, et séquentielle. Les tâches planifiées ne sont donc pas exécutées en parallèle des actions du blog, mais avant ou après.
  • Un blog WordPress ne fonctionne que lorsqu’il est requêté. Donc si aucun visiteur ne clique sur un lien, si aucune page n’est demandée, rien ne s’exécute.

Conséquences:

  • Les tâches planifiées impactent directement les temps de réponse du site, puisque leur temps d’exécution se cumule au temps d’exécution des tâches interactives,
  • Les heures et les fréquences spécifiées ne seront pas forcement strictement suivies. Si un blog attire 10 visiteurs par jour entre 08h00 et 18h00 (1 clic par heure), il est complètement inutile de spécifier une fréquence de 5minutes, vous n’aurez, de toute façon, rien de plus qu’une seule exécution par heure.

Je reviendrai ces deux points un peu plus bas dans l’article.

Principe

A quel moment créer la tâche?

La plupart des actions exécutées par WordPress (hooks ou filtres), le sont à chaque fois que l’outil charge une page. Donc, si nous utilisons une action ou un filtre habituel pour créer notre tâche, nous risquons d’ajouter la même tâche à chaque fois que WordPress sera requêté.

La méthode communément décrite consiste à utiliser les hooks register_activation_hook et register_deactivation_hook pour la création et la
suppression des tâches planifiées. Ces hooks ne sont, en effet, appelés qu’une seule fois pendant l’activation, et la désactivation des plugins.

Attention à la planification « implicite » des tâches lors de l’activation des plugins. Elle peut être gênante. J’y reviendrai en fin d’article.

Les paramètres temporels

La phase de création d’une tâche planifiée consiste à désigner la fonction à exécuter, et l’heure ou la fréquence d’exécution. Designer la fonction à exécuter s’effectue en deux temps:

  • Création d’un hook: add_action( $hook, 'ma_fonction');
  • Désignation du hook comme action planfiée: wp_schedule_event( $timestamp, $recurrence, $hook, $args )

Dans l’appel à wp_schedule_event, $timestamp désigne l’heure approximative à laquelle la fonction doit s’exécuter. Si l’on veut que la fonction s’exécute plusieurs fois, à intervalle régulier, il faut indiquer également une fréquence, du type journalier (daily), hebdomadaire (weekly) …
Pour offrir plus de souplesse aux développeurs, WordPress ne dispose pas d’une liste fixe, pré-définie de ces fréquences. Il nous laisse la possibilité d’ajouter nos propres fréquences.
Pour commencer, la table des fréquences est accessible avec la fonction wp_get_schedules(). Cette fonction renvoie une table qui prend la forme suivante:

Array (
    [hourly] => Array (
        [interval] => 3600
        [display]  => 'Once hour' )
    [twicedaily]  => Array (
        [interval] => 43200
        [display]  => 'Twice a day' )
    [daily]         => Array (
        [interval] => 86400
        [display]  => 'Once a day' )
)

La méthode pour ajouter nos propres fréquences est basée sur un filtre:

function my_schedules() {
    return array(
		'halfhour' => array(
			'interval' => 1800, /* 60 seconds * 30 minutes */
			'display' => 'Twice hour'
		),
		'weekly' => array(
			'interval' => 604800, /* 60 seconds * 60 minutes * 24 hours * 7 days */
			'display' => 'Weekly'
		)
);
}
add_filter('cron_schedules', 'my_schedules');

Création de la tâche proprement dite

A ce stade, nous savons spécifier l’heure et la fréquence, il ne reste plus qu’à indiquer ce que nous voulons faire:

if (!wp_next_scheduled('my_task_hook')) {
    wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}
add_action( 'my_task_hook', 'my_task_function' ); 
 
function my_task_function() {
    // actions to execute
}

Quelques commentaires:

  • En ligne 1, nous vérifions que la tâche n’existe pas déjà,
  • L’ajout proprement dit de la tâche est réalisé en ligne 2,
  • La fonction wp_schedule_event est basée sur un hook, qu’il faut donc créer (ligne 3),
  • Enfin, en ligne 6, nous créons la tâche proprement dite.

L’API disponible

La plupart des fonctions disponibles se trouvent dans le fichier wp-includes/cron.php. L’API comporte deux composantes: des fonctions, et des filtres.

Les fonctions

Fonction Paramètres Commentaires
wp_schedule_single_event timestamp,
hook
Permet de planifier une tâche en vue d’une execution unique
wp_schedule_event >timestamp,
hook,
recurrence,
$args
Permet de planifier une tâche récurrente. La première exécution aura lieu à l’heure spéficiées
wp_clear_scheduled_hook hook Supprime une tâche planifiée. A noter qu’il existe également la fonction wp_unschedule_event, qui est pratiquement inutilisable parce qu’elle nécessite l’heure exacte de la prochaine exécution.
wp_next_scheduled hook,
[args]
Permet d’obtenir l’heure et la date du prochain déclenchement de l’action spécifiée. Très utile pour savoir si une action est déjà planifiée ou pas.
wp_get_schedule hook,
[args]
Renvoie les paramètres temporels de la tâche spécifiée
wp_get_schedules aucun Renvoie la liste des fréquences disponibles.

Les filtres

Fonction Paramètres Commentaires
cron_schedules aucun Permet d’ajouter une fréquence à la liste déjà existante.

Contraintes et précautions

Les tâches planifiées peuvent s’exécuter en dehors de toute connexion à l’interface d’administration. Toute référence a l’utilisateur courant se soldera donc par un échec.

Par nature, ces tâches ne sont pas interactives. Donc les commandes echo, print, ou les commandes d’internationalisation __(), ou _e() ne servent à rien. Tout doit se faire, soit dans la base de données, soit dans des fichiers.

Comme nous l’avons vu précédemment, WordPress n’est pas un système d’exploitation multi-tâche. Les tâches planifiées ne s’exécutent pas parallèlement aux tâches interactives (interface d’administration, ou partie publique du site).

Au moment de l’exécution d’une tâche planifiée, WordPress devra donc exécuter cette tâche, puis effectuer son travail habituel pour afficher la page demandée. Plus la tâche planifiée sera lourde, plus le chargement de la page sera long.

Il faudra donc rester raisonnable sur deux aspects:

  • La fréquence d’exécution: une tâche toutes les 5 minutes sera forcement plus pénalisante que la même tâche toutes les heures,
  • Le travail effectué dans chacune des tâches: évitez les requêtes trop lourdes.

Deux approches pour « cacher » l’impact des tâches planifiées sur les performances:

  • Prévoir ces tâches à des heures « creuses »: si le site est en français, et ne s’adresse qu’à une population française, vous pouvez choisir des heures comprises entre 1 heures et 6 heures du matin. Le problème dans ce cas est d’être sûre que quelqu’un passera à ce moment, car si le site n’est pas requêté, les tâches ne seront pas executes!
  • Fragmenter les tâches à effectuer, c’est-à-dire prévoir des actions qui peuvent se décomposer en petites opérations courtes et rapides. Les actions ne s’effectuera donc pas en une seule fois, mais en plusieurs, et une action ne sera complète, que lorsque toutes ces opérations seraient exécutées.

Je pense que la seconde approche est la plus saine, mais également la plus difficile à gérer.

Conclusion

Les fonctions proposées par WordPress pour gérer les tâches planifiées sont rudimentaires, mais elles sont simples à utiliser, et couvrent largement les besoins.

Compte-tenu de la nature et du mode de fonctionnement de WordPress, ces besoins doivent obligatoirement être limités. Un trop grand nombre, ou une trop grande complexité des tâches entraînera, en effet, d’inévitables problèmes de performance. Donc, même s’il est facile de créer une tâche planifiée pour un plugin, il est ne faudra le faire qu’en cas d’absolue nécessité.

Un autre point me paraît également important: les administrateurs doivent garder le contrôle absolu de leur blog. Cela implique deux choses:

  • d’abord il faut clairement documenter les tâches planifiées, en expliquant ce qu’elles font, quelle charge elles créent, en combien de temps elles s’exécutent…
  • Ensuite, donner aux administrateurs, la possibilité d’activer ou désactiver ces tâches à tout moment.

Donc, contrairement à ce que l’on peut lire un peu partout, je ne conseille pas de créer les tâches planifiées pendant l’activation du plugin, mais plutôt de permettre cette activation dans une des pages du plugin (dans les options par exemple). De cette façon, l’activation est explicite (non masquée), et l’administrateur peut aisément faire des études d’impact, en analysant les performances de son blog, avec, puis sans les tâches planifiées.

6 thoughts on “Tâches planifiées avec WordPress”

  1. Bonjour,
    Désirant créer une newsletter sous WP, je viens de découvrir le plugin « Newsletter Manager » qui me semble convenir à ce que je recherche. Le hic, c’est que l’automatisation des envois nécessite un « cron » (d’où ma découverte de votre article que je trouve très intéressant, même pour le néophyte que je suis) à effectuer sur le serveur de l’hébergeur, dixit l’auteur de ce plugin, chose que je ne vois absolument pas comment faire étant donné mon peu de connaissances en la matière. Pouvez-vous me donner quelques tuyaux sur la marche à suivre concrètement ?
    Pour info, le site concerné est hébergé chez OVH.
    Je vous remercie par avance de votre aide.
    Cordialement.

  2. Effectivement, si la base est importante, le backup risque de ne pas passer inaperçu.
    Même avec un « reminder », il faut beaucoup de discipline pour faire un backup manuel régulier. C’est pourquoi j’ai opté pour un backup planifié.
    Sinon la solution pour ceux qui disposent d’un serveur dédié, est d’utiliser directement la commande mysql_dump, et de planifier l’exécution de l’outil dans la crontab.

  3. Ah je ne comprenais pas comment PHP faisait pour programmer des actions je comprends mieux ! Merci 😉

    Par contre ça veut dire qu’une fois par semaine, lorsqu’un utilisateur viens sur mon blog, il déclenche la sauvegarde de la BDD et patiente une bonne vingtaine de secondes avant de voir mon blog. Peut être qu’une alerte iCal et une backup manuelle serait plus appropriée 😮

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.