vendredi 25 septembre 2026

À propos

Contact

IA & MCP

File d’attente pour appels IA : Action Scheduler et reprises sur erreur

Traiter des milliers d'appels IA en tâche de fond avec Action Scheduler, en respectant les limites de débit du fournisseur et en gérant les reprises sur erreur.

Par Clément Hadrot • 17 septembre 2024 • 5 min de lecture • Aucun commentaire
File d'attente pour appels IA : Action Scheduler et reprises sur erreur

Migrer un catalogue de huit mille fiches produits vers des descriptions reformulées par IA ne se fait pas en une boucle foreach lancée depuis une tâche cron unique : au-delà de quelques centaines d’appels, on se heurte aux limites de débit du fournisseur, aux timeouts d’exécution PHP, et à l’absence totale de visibilité sur l’avancement réel du traitement. Cet article documente l’architecture que nous avons mise en place pour ce type de volume, avec Action Scheduler comme colonne vertébrale.

Cet article ne traite pas la question du coût de ces appels en volume, abordée séparément : il se concentre sur l’architecture de traitement en file d’attente elle-même.

Pourquoi une tâche cron classique ne suffit pas

Une tâche déclenchée par wp_schedule_event() s’exécute dans le cycle de vie classique d’une requête WordPress, avec une limite de temps d’exécution PHP qui rend impossible le traitement de plusieurs milliers d’appels API en une seule fois. Action Scheduler, la bibliothèque utilisée notamment par WooCommerce, résout ce problème en planifiant chaque unité de travail comme une action indépendante, traitée par lots successifs sans dépendre d’une seule exécution longue.

Mettre en file d’attente une action par élément à traiter

Plutôt que de planifier une seule grosse tâche, on planifie une action distincte par fiche produit à traiter, avec un léger décalage entre chacune pour respecter les limites de débit imposées par le fournisseur d’API.

function wpm_mettre_en_file_reformulation( array $ids_produits ) {
    $delai = 0;

    foreach ( $ids_produits as $id_produit ) {
        as_schedule_single_action(
            time() + $delai,
            'wpm_reformuler_description',
            array( 'produit_id' => $id_produit ),
            'wpm-reformulation-ia'
        );

        $delai += 3; // Trois secondes entre chaque appel, pour respecter le débit autorisé.
    }
}
L'essentiel à retenir : Jamais plus de N appels simultanés ; Retry exponentiel avant abandon définitif ; Suivi de l'avancement consultable par l'équipe

Le traitement individuel, avec gestion des erreurs

Le callback exécuté pour chaque action gère l’appel à l’API, mais aussi le cas d’échec, en distinguant les erreurs qui justifient une nouvelle tentative de celles qui n’en justifient pas.

add_action( 'wpm_reformuler_description', function ( $produit_id ) {
    $description = get_post_field( 'post_content', $produit_id );

    $reponse = wp_remote_post( 'https://api.openai.com/v1/chat/completions', array(
        'timeout' => 20,
        'headers' => array(
            'Authorization' => 'Bearer ' . WPM_LLM_API_KEY,
            'Content-Type'  => 'application/json',
        ),
        'body'    => wp_json_encode( array(
            'model'    => 'gpt-4o-mini',
            'messages' => array(
                array( 'role' => 'user', 'content' => 'Reformule cette description produit : ' . $description ),
            ),
        ) ),
    ) );

    $code_statut = wp_remote_retrieve_response_code( $reponse );

    if ( is_wp_error( $reponse ) || 429 === $code_statut || $code_statut >= 500 ) {
        wpm_replanifier_avec_retry( $produit_id );
        return;
    }

    if ( 200 !== $code_statut ) {
        update_post_meta( $produit_id, '_wpm_reformulation_statut', 'echec_definitif' );
        return;
    }

    $corps = json_decode( wp_remote_retrieve_body( $reponse ), true );
    update_post_meta( $produit_id, '_wpm_description_reformulee', $corps['choices'][0]['message']['content'] ?? '' );
    update_post_meta( $produit_id, '_wpm_reformulation_statut', 'terminee' );
} );

Le retry exponentiel, pour ne pas aggraver une limite de débit

En cas d’erreur 429, qui signale un dépassement de la limite de débit, réessayer immédiatement ne ferait qu’aggraver le problème. Le délai avant nouvelle tentative augmente donc à chaque échec, jusqu’à un nombre maximal de tentatives au-delà duquel l’action est marquée en échec définitif plutôt que retentée indéfiniment.

function wpm_replanifier_avec_retry( $produit_id ) {
    $tentatives = (int) get_post_meta( $produit_id, '_wpm_tentatives', true );

    if ( $tentatives >= 3 ) {
        update_post_meta( $produit_id, '_wpm_reformulation_statut', 'echec_definitif' );
        return;
    }

    update_post_meta( $produit_id, '_wpm_tentatives', $tentatives + 1 );
    $delai = pow( 2, $tentatives ) * 60; // 60s, puis 120s, puis 240s.

    as_schedule_single_action(
        time() + $delai,
        'wpm_reformuler_description',
        array( 'produit_id' => $produit_id ),
        'wpm-reformulation-ia'
    );
}

Suivre l’avancement sans deviner

Sur un lot de huit mille fiches, l’équipe cliente avait besoin de savoir où en était le traitement sans consulter les logs serveur. Une page d’administration simple interroge les métadonnées de statut pour afficher un décompte par état : en attente, terminé, échec définitif, avec un bouton pour relancer manuellement les échecs.

Ce que cette architecture a permis de tenir

Le lot complet de huit mille fiches s’est traité en un peu moins de deux jours, sans intervention manuelle, avec un taux d’échec définitif inférieur à 1 %, principalement des fiches au contenu source vide ou corrompu, détectées et signalées pour un traitement manuel séparé.

Une file d’attente qui ne sait pas dire où elle en est n’est pas beaucoup plus rassurante qu’une boucle qui tourne en silence. Le suivi d’avancement n’est pas un confort, c’est une condition de confiance de l’équipe cliente.

Notre verdict

Pour tout traitement en volume, Action Scheduler apporte exactement ce qu’une boucle simple ne peut pas offrir : un traitement par unité indépendante, un espacement contrôlé des appels, et une reprise sur erreur qui ne demande aucune surveillance humaine constante pendant l’exécution.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi