# Republier un article déjà publié en boucle sature la file wp-cron

> Un événement cron jamais désinscrit après une modification de contenu peut, en s'accumulant silencieusement, finir par saturer la file d'attente de wp-cron.

- Auteur : WordPress Développement
- Publié le : 2024-08-19
- Mis à jour le : 2024-08-19
- Catégorie : Performance
- URL : https://www.wpmoderne.fr/performance/republier-article-boucle-wp-cron/

## L’essentiel

- Un événement cron mal désinscrit se réinscrit à chaque republication
- La file grossit silencieusement jusqu'à ralentir chaque requête
- wp_clear_scheduled_hook corrige la source, pas seulement le symptôme

`wp cron event list` renvoyait plus de mille quatre cents lignes sur un site d'actualités locales, alors qu'un site de cette taille ne devrait raisonnablement en compter que quelques dizaines à un instant donné. Chaque requête visiteur, en l'absence de cron système externe, déclenchait la vérification de cette liste entière avant de décider si un événement devait s'exécuter, ajoutant un coût silencieux à chaque affichage de page.

Le symptôme initial ressemblait à un ralentissement général et diffus du site, sans page précise identifiable comme responsable. Le diagnostic a mené à un comportement récurrent : la republication d'un même article, plusieurs fois par jour dans le cadre d'une politique éditoriale de mise à jour de contenu, réinscrivait systématiquement un événement cron sans jamais désinscrire les précédents.

## Diagnostic : retrouver la source de l'accumulation

Une extension maison, chargée de republier un rappel de notification par e-mail cinq minutes après chaque mise à jour d'un article, programmait cet événement via `wp_schedule_single_event()` à chaque déclenchement du hook `save_post`, sans jamais vérifier au préalable si un événement similaire existait déjà pour cet article :

```
// Code fautif : aucune vérification avant la programmation
add_action( 'save_post', function ( $post_id ) {
    wp_schedule_single_event(
        time() + 5 * MINUTE_IN_SECONDS,
        'notifier_mise_a_jour_article',
        array( $post_id )
    );
} );
```

Sur un article republié dix fois par jour, pendant plusieurs semaines, ce code accumulait un événement cron distinct à chaque republication, sans jamais nettoyer les anciens événements déjà exécutés ou devenus obsolètes, en particulier lorsque l'article était republié avant même que le premier événement de cinq minutes ne se soit déclenché.

> L'essentiel à retenir : Un événement cron mal désinscrit se réinscrit à chaque republication ; La file grossit silencieusement jusqu'à ralentir chaque requête ; wp_clear_scheduled_hook corrige la source, pas seulement le symptôme

## Correctif : vérifier avant de programmer, et désinscrire l'ancien

La correction consiste à vérifier systématiquement si un événement existe déjà pour cet article précis avant d'en programmer un nouveau, et à désinscrire explicitement tout événement précédent devenu redondant :

```
add_action( 'save_post', function ( $post_id ) {
    $args = array( $post_id );

    // Désinscrire tout événement précédent pour cet article
    $timestamp_existant = wp_next_scheduled( 'notifier_mise_a_jour_article', $args );
    if ( $timestamp_existant ) {
        wp_unschedule_event( $timestamp_existant, 'notifier_mise_a_jour_article', $args );
    }

    wp_schedule_single_event(
        time() + 5 * MINUTE_IN_SECONDS,
        'notifier_mise_a_jour_article',
        $args
    );
} );
```

La fonction `wp_clear_scheduled_hook()` offre une alternative plus radicale quand plusieurs occurrences doivent être supprimées d'un coup, en désinscrivant toutes les instances programmées d'un hook donné pour des arguments identiques, plutôt que de traiter une seule occurrence à la fois.

## Nettoyer l'accumulation déjà présente

Une fois la source corrigée, les événements déjà accumulés restent en base de données jusqu'à leur exécution naturelle ou leur suppression manuelle. Un nettoyage via WP-CLI permet de purger rapidement les doublons identifiés :

```
wp cron event list --hook=notifier_mise_a_jour_article --format=csv
wp cron event delete notifier_mise_a_jour_article
```

Cette commande supprime l'ensemble des occurrences programmées pour ce hook précis, offrant un point de départ propre avant que le code corrigé ne reprenne la main sur les futures programmations.

## Prévention : les réflexes à adopter

- Toujours vérifier l'existence d'un événement avec `wp_next_scheduled()` avant d'en programmer un nouveau pour les mêmes arguments.
- Préférer `wp_schedule_single_event()` à un événement récurrent quand la logique métier ne nécessite qu'une seule exécution différée, pour limiter le risque d'accumulation en cas de logique de désinscription manquante.
- Surveiller périodiquement la taille de la file cron via `wp cron event list`, en particulier après l'ajout d'une extension qui programme des événements en réaction à des actions fréquentes du contenu.

## En résumé

Un événement cron mal désinscrit reste discret jusqu'à ce que son accumulation devienne suffisamment massive pour ralentir chaque requête entrante, chargée de vérifier une file toujours plus longue. Vérifier systématiquement l'existence d'un événement avant sa programmation, et désinscrire proprement les occurrences devenues redondantes, évite cette dérive silencieuse qui finit toujours par se remarquer trop tard.
