WP Cron ne s'exécute pas à la fin du temps

15

L'objectif

Je souhaite utiliser wp_schedule_single_event( ) pour exécuter un événement unique qui m'envoie un courrier électronique 8 minutes après que l'utilisateur a envoyé un formulaire.

Le problème

Le code suivant se trouve dans mon functions.php :

function nkapi_send_to_system( $args ) {
  wp_mail( 'xxx', 'xxx', $args );
}

add_action( 'nkapi_send', 'nkapi_send_to_system' );

function schedule_event( $id ) {
  wp_schedule_single_event( current_time( 'timestamp' ) + 480, 'nkapi_send', array( $id ) );
}

Et le code suivant est utilisé pour appeler schedule-event :

schedule_event( $_SESSION['insert_id'] ); // the $_SESSION var contains an INT

Après avoir attendu plus de 8 minutes, aucun courrier électronique ne se trouvait dans ma boîte de réception.

Ce que j'ai essayé

Le plugin Core Control permet de voir quels travaux cron sont planifiés.

Aprèsquelquesmodifications,j'airéussiàlescorriger,etmieuxencore,lorsquejecliquesur"Run Now", je reçois un courrier électronique dans ma boîte de réception.

Mais pourquoi le cron ne s’exécute pas lorsque je visite mon site après 8 minutes. Quel est le problème avec ce code? Je dois dire que c’est la première fois que j’utilise WP Cron.

J'ai essayé plus

Après le commentaire de vancoder , id a décidé de vérifier si le code fonctionne si je mets le code suivant directement dans le functions.php :

function schedule_event( $id ) {
  wp_schedule_single_event( time(), 'nkapi_send', array( $id ) );
}

if ( isset( $_SESSION['insert_id'] ) ) {
  if ( ! array_key_exists( 'insert_scheduled', $_SESSION ) || $_SESSION['insert_scheduled'] != $_SESSION['insert_id'] ) {
    schedule_event( $_SESSION['insert_id'] );
    $_SESSION['insert_scheduled'] = $_SESSION['insert_id'];
  }
}

L'inconvénient de ce code est que l'utilisateur doit accéder à une autre page avant que ce code ne soit exécuté. Mais de l’autre côté, cela ne marche pas non plus, alors ce ne serait pas mon premier problème ...

    
posée Mike Madern 27.03.2013 - 16:12

4 réponses

8

Tout d'abord, pouvez-vous s'il vous plaît confirmer que vous n'avez aucun plugin de cache activé? Les plugins de cache peuvent interférer avec les tâches cron car vos visiteurs ne reçoivent pas une page en direct mais une version mise en cache de votre page.

Si un plug-in de mise en cache est activé, vous pouvez choisir l'une de vos pages, ajouter une exclussion aux paramètres de votre plug-in de mise en cache pour cette page afin qu'elle ne soit jamais mise en cache.

Ensuite, vous devrez créer manuellement un travail cron (à l'aide de cpanel si vous êtes sur un environnement d'hébergement partagé ou à partir du terminal s'il s'agit d'un serveur VPS / dédié) qui visitera cette page toutes les quelques minutes.

J'espère que cela aide!

    
réponse donnée WPMU-DEV Ari 05.04.2013 - 16:59
13

Définissez d’abord vos plannings de tâches cron personnalisés.

add_filter('cron_schedules', array($this, 'cron_schedules'));

public function cron_schedules($schedules){
    $prefix = 'cron_';// Avoid conflict with other crons. Example Reference: cron_30_mins
    $schedule_options = array(
        '30_mins' => array(
            'display' => '30 Minutes',
            'interval' => '1800'
        ),
        '1_hours' => array(
            'display' => 'Hour',
            'interval' => '3600'
        ),
        '2_hours' => array(
            'display' => '2 Hours',
            'interval' => '7200'
        )
    );
    /* Add each custom schedule into the cron job system. */
    foreach($schedule_options as $schedule_key => $schedule){
        $schedules[$prefix.$schedule_key] = array(
            'interval' => $schedule['interval'],
            'display' => __('Every '.$schedule['display'])
        );
     }
     return $schedules;
}

Vous devez décider où et quand planifier réellement l'événement.

Voici juste un exemple de code qui appelle la méthode de classe personnalisée:

$schedule = $this->schedule_task(array(
    'timestamp' => current_time('timestamp'), // Determine when to schedule the task.
    'recurrence' => 'cron_30_mins',// Pick one of the schedules set earlier.
    'hook' => 'custom_imap_import'// Set the name of your cron task.
));

Voici le code qui planifie réellement l'événement:

private function schedule_task($task){
    /* Must have task information. */
    if(!$task){
        return false;
    }
    /* Set list of required task keys. */
    $required_keys = array(
        'timestamp',
        'recurrence',
        'hook'
    );
    /* Verify the necessary task information exists. */
    $missing_keys = array();
    foreach($required_keys as $key){
        if(!array_key_exists($key, $task)){
            $missing_keys[] = $key;
        }
    }
    /* Check for missing keys. */
    if(!empty($missing_keys)){
        return false;
    }
    /* Task must not already be scheduled. */
    if(wp_next_scheduled($task['hook'])){
        wp_clear_scheduled_hook($task['hook']);
    }
    /* Schedule the task to run. */
    wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
    return true;
}

Maintenant, tout ce que vous avez à faire est d’appeler le nom de votre tâche périodique personnalisée. Dans cet exemple, le nom de la tâche périodique est custom_imap_import .

add_action('custom_imap_import', array($this, 'do_imap_import'));

public function do_imap_import(){
    // .... Do stuff when cron is fired ....
}

Ainsi, dans cet exemple, $this->do_imap_import(); est appelé toutes les 30 minutes (en supposant que le trafic sur votre site Web soit suffisant).

Notes

Nécessite une visite de la page pour que votre ordinateur puisse se déclencher à l'heure correcte.

Exemple: si vous avez planifié une tâche à 30 minutes d'intervalle, mais que personne ne visite votre site pendant 4 heures, votre travail cron ne sera pas déclenché tant que ce visiteur ne viendra pas sur votre site 4 heures plus tard. . Si vous avez vraiment besoin que votre tâche soit renvoyée toutes les 30 minutes, il est conseillé de configurer une tâche cron légitime via votre fournisseur d’hébergement Web pour visiter votre site Web aux intervalles souhaités.

Les travaux cron de WordPress ne ralentissent pas votre site Web!

Vous pensez peut-être que si l'exécution du script cron prend beaucoup de temps, les visiteurs devront-ils attendre jusqu'à ce que le script soit exécuté. Nan! Comment cela peut-il être possible? Si vous regardez le fichier wp-cron.php , vous trouverez une ligne

ignore_user_abort(true);

C’est une configuration php.ini qui définit que, si vous arrêtez de charger le site / script, le script ne s’arrête pas de s’exécuter.

Si vous regardez le fichier wp-includes/cron.php , vous verrez une ligne comme celle-ci:

wp_remote_post( $cron_url, 
array('timeout' => 0.01,
 'blocking' => false, 
 'sslverify' => apply_filters('https_local_ssl_verify', true)) );

Cela signifie que WordPress n’attendra que 0,01 seconde pour le déclenchement de l’exécution, puis il abandonnera mais comme vous avez défini ignore_user_abort sur true , le script sera exécuté. Cette fonctionnalité est un avantage considérable pour l’exécution de scripts volumineux dans les travaux cron de WordPress.

Fonctions disponibles pour l'aide:

réponse donnée Michael Ecklund 04.04.2013 - 16:22
3

WordPress Cron vous permet de planifier des tâches, mais celles-ci ne seront exécutées que si une demande est faite au site. Pour chaque demande reçue par WordPress, il vérifie s'il existe des tâches cron à traiter et, le cas échéant, déclenche une demande asynchrone à /wp-cron.php?doing_wp_cron pour traiter la tâche. Si le démarrage planifié d'un travail se passe sans demande, le processus cron ne sera pas lancé.

Etant donné que vous pouvez voir et exécuter vos travaux planifiés, il est possible qu'aucune demande ne déclenche le démarrage du travail cron, en particulier si vous utilisez un plug-in de mise en cache. La meilleure option pour décharger cela dans un calendrier plus régulier consiste à désactiver la vérification par défaut dans WordPress et à utiliser crontab .

Tout d'abord pour désactiver la vérification par défaut (ce qui peut aider un peu aux performances côté client), ajoutez ce qui suit à wp-config.php :

// Disable default check for WordPress cron jobs on page loads
define( 'DISABLE_WP_CRON', true );

Vous créez ensuite une tâche pour extraire la page wp-cron.php une fois par minute afin de traiter les travaux du serveur principal. À partir de la ligne de commande, entrez crontab -e , puis ajoutez une ligne semblable à celle-ci:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
    
réponse donnée doublesharp 06.04.2013 - 02:43
0

Vérifiez que DISABLE_WP_CRON n'est pas défini dans votre configuration.

En cas d'échec, essayez de désactiver tous les plug-ins (à l'exception du contrôle de base - bien que j'utiliserais wp-crontrol) et voir si vos travaux de base fonctionnent. Si tel est le cas, vous rencontrez des interférences de plug-ins quelque part.

De même, essayez de passer à un thème standard de la vingtaine d'années.

Si rien de tout cela ne change rien, il y a de strongs chances que ce soit un problème d'hébergement.

    
réponse donnée vancoder 04.04.2013 - 19:19

Lire d'autres questions sur les étiquettes