Le WordPress d'aujourd'hui, décodé pour les développeurs

Performance

Un wp_remote_request bloquant dans save_post ralentit chaque publication

L'auteur qui clique sur « Publier » attend parfois plusieurs secondes, sans savoir qu'un appel HTTP synchrone tourne en coulisses avant l'affichage de la confirmation.

Par WordPress Développement • 5 août 2023 • 4 min de lecture • Aucun commentaire
Un wp_remote_request bloquant dans save_post ralentit chaque publication

Ce qu’on observe d’abord, c’est une plainte récurrente des rédacteurs : « publier un article prend parfois cinq à huit secondes, parfois c’est instantané ». Ce genre de variation, sans lien apparent avec la taille du contenu, pointe presque toujours vers un appel réseau synchrone caché dans un hook d’enregistrement.

Sur le site en question, l’enquête a mené à une extension maison qui synchronisait chaque publication avec un service de recommandation de contenu externe, via un appel wp_remote_post() exécuté directement dans le hook save_post.

Pourquoi ce hook est un mauvais endroit pour un appel bloquant

Le hook save_post s’exécute de façon synchrone, dans le même cycle de requête que le clic sur le bouton « Publier » ou « Mettre à jour ». Tant que le code accroché à ce hook ne rend pas la main, l’interface d’administration reste bloquée sur un indicateur de chargement, et l’auteur ne récupère le contrôle qu’une fois l’ensemble des traitements terminés.

add_action( 'save_post', function ( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) {
        return;
    }

    // Appel bloquant : le navigateur de l'auteur attend la réponse.
    wp_remote_post( 'https://service-recommandation.example/sync', array(
        'timeout' => 10,
        'body'    => array( 'post_id' => $post_id ),
    ) );
} );

Le paramètre timeout fixé à dix secondes illustre bien le problème : si le service distant répond en huit secondes un jour de charge, l’auteur attend huit secondes de plus avant de voir son article confirmé comme publié, sans qu’aucun message n’explique ce délai.

Ce que cela coûte à chaque publication

Le coût ne se limite pas à l’inconfort ressenti par l’auteur. Sur un site à plusieurs rédacteurs publiant en simultané, chaque appel synchrone occupe un processus PHP-FPM pendant toute sa durée, réduisant d’autant le nombre de processus disponibles pour traiter d’autres requêtes, y compris celles des visiteurs du site public. Un pic de publications (par exemple une salve d’articles programmés au même moment) peut ainsi saturer temporairement le pool de processus.

L'essentiel à retenir : Un appel HTTP synchrone dans save_post bloque toute la publication ; L'auteur subit le délai de réponse d'un service tiers ; Reporter l'appel en arrière-plan restaure l'instantanéité

Comment reporter l’appel en tâche asynchrone

La solution consiste à ne plus exécuter l’appel HTTP dans le flux synchrone de save_post, mais à le planifier immédiatement via le système de cron de WordPress, pour une exécution quasi immédiate mais détachée de la requête de l’auteur :

add_action( 'save_post', function ( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) {
        return;
    }

    if ( ! wp_next_scheduled( 'sync_vers_recommandation', array( $post_id ) ) ) {
        wp_schedule_single_event( time(), 'sync_vers_recommandation', array( $post_id ) );
    }
} );

add_action( 'sync_vers_recommandation', function ( $post_id ) {
    wp_remote_post( 'https://service-recommandation.example/sync', array(
        'timeout' => 10,
        'body'    => array( 'post_id' => $post_id ),
    ) );
} );

Avec cette approche, save_post ne fait plus que programmer un événement ponctuel, une opération quasi instantanée en base de données. L’appel HTTP proprement dit s’exécute lors du prochain déclenchement de wp-cron, en dehors de la requête de l’auteur, qui récupère immédiatement le contrôle de son interface.

Une alternative pour les sites à fort trafic de publication

Sur un site où wp-cron est désactivé au profit d’un vrai cron système (une pratique courante en production pour éviter les déclenchements liés au trafic visiteur), il faut s’assurer que le cron système tourne assez fréquemment pour que le délai entre la programmation et l’exécution reste acceptable, en général une exécution par minute suffit largement pour ce type de synchronisation différée.

  • Vérifiez toujours si un événement est déjà programmé avant d’en ajouter un nouveau, pour éviter d’empiler des appels redondants sur un même article modifié plusieurs fois rapidement.
  • Ajoutez une temporisation ou une déduplication si l’article peut être enregistré plusieurs fois en quelques secondes (autosave, révisions).
  • Journalisez les échecs de l’appel différé : contrairement à un appel synchrone, une erreur ici ne remonte plus jamais à l’utilisateur.

En résumé

Aucun appel réseau synchrone ne devrait rester accroché à save_post dès lors que sa réponse n’est pas indispensable à l’affichage de la confirmation de publication. Le report via wp_schedule_single_event() restaure une expérience de publication instantanée pour l’auteur, tout en libérant plus rapidement les processus PHP-FPM sollicités par l’administration.

Laisser un commentaire

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

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi