WP Cron no se ejecuta cuando pasa el tiempo

15

El objetivo

Quiero usar wp_schedule_single_event( ) para ejecutar un solo evento que me envíe un correo electrónico 8 minutos después de que el usuario envíe un formulario.

El problema

El siguiente código está en mi 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 ) );
}

Y el siguiente código se usa para llamar a schedule-event :

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

Después de esperar más de 8 minutos, no había un correo electrónico en mi bandeja de entrada.

Lo que probé

Con el complemento Core Control es posible ver qué tareas cron están programadas.

Despuésdeunpardecambioslogréquefueranbastantecorrectos,ymejor,cuandopresioné"Ejecutar ahora", recibí un correo electrónico en mi bandeja de entrada.

Pero, ¿por qué no se ejecutan los crons cuando visito mi sitio después de 8 minutos? ¿Qué es lo que está mal con este código? Tengo que decir que esta es la primera vez que utilizo WP Cron.

Intenté más

Después del comentario de vancoder , el ID decidió probar si el código funciona si pongo el siguiente código directamente en el 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'];
  }
}

La desventaja de este código es que el usuario tiene que ir a otra página antes de que se ejecute este código. Pero por otro lado, esto tampoco funciona, por lo que no sería mi primer problema ...

    
pregunta Mike Madern 27.03.2013 - 16:12

4 respuestas

8

Primero, ¿puede confirmar que no tiene ningún complemento de almacenamiento en caché habilitado? Los complementos de almacenamiento en caché pueden interferir con los trabajos cron porque sus visitantes no reciben una página activa sino una versión en caché de su página.

Si tiene un complemento de almacenamiento en caché habilitado, puede elegir una de sus páginas, agregar una exclusión a la configuración de su complemento de almacenamiento en caché para esa página para que nunca se almacene en caché.

Luego, tendrá que crear manualmente un trabajo cron (usando cpanel si está en un entorno de alojamiento compartido o desde la terminal si es un VPS / servidor dedicado) que visitará esa página cada pocos minutos.

Espero que ayude!

    
respondido por el WPMU-DEV Ari 05.04.2013 - 16:59
13

En primer lugar, defina sus cronogramas de trabajo cron personalizados.

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;
}

Debe decidir dónde y cuándo programar realmente el evento.

Aquí hay solo un fragmento de código de ejemplo, que realiza una llamada a un método de clase personalizado:

$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.
));

Aquí está el código que realmente programa el evento:

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;
}

Ahora, todo lo que necesita hacer es llamar al nombre de su tarea cron personalizada. En este ejemplo, el nombre de la tarea cron es custom_imap_import .

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

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

En este ejemplo, $this->do_imap_import(); se llama cada 30 minutos (suponiendo que tenga suficiente tráfico para su sitio web).

Notas

Requiere una visita a la página para que su cron se active en los momentos correctos.

Ejemplo: Si programó una tarea a intervalos de 30 minutos, pero nadie visita su sitio durante 4 horas, su trabajo cron no se activará hasta que el visitante llegue a su sitio 4 horas después. . Si realmente necesita que su tarea se realice cada 30 minutos, se recomienda configurar un trabajo cron legítimo a través de su proveedor de alojamiento web para que visite su sitio web a los intervalos deseados.

¡Los trabajos cron de WordPress no hacen que su sitio web sea lento!

Tal vez esté pensando qué pasará si el cron-script demora mucho tiempo en ejecutarse, ¿tendrán que esperar los visitantes hasta que se ejecute el script? No ¿Cómo puede ser posible? Si observa el archivo wp-cron.php , encontrará una línea

ignore_user_abort(true);

Es una configuración php.ini que establece que si dejas de cargar el sitio / script, el script no dejará de ejecutarse.

Si observa el archivo wp-includes/cron.php , encontrará una línea como esta:

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

Eso significa que WordPress esperará solo 0.01 segundos para desencadenar la ejecución, luego abortará, pero como ha establecido ignore_user_abort en true , el script se ejecutará. Esta funcionalidad es una gran ventaja para ejecutar scripts de gran tamaño en trabajos cron de WordPress.

Funciones disponibles para ayuda:

respondido por el Michael Ecklund 04.04.2013 - 16:22
3

WordPress Cron le permite programar tareas, pero solo se ejecutarán si se realiza una solicitud al sitio. Para cada solicitud que recibe WordPress, verificará si hay tareas cron para procesar, y si es así, se dispara una solicitud a /wp-cron.php?doing_wp_cron asincrónicamente para procesar la tarea. Si el inicio programado de un trabajo pasa sin una solicitud, no se iniciará el proceso cron.

Como puede ver y ejecutar sus trabajos programados, es posible que no haya solicitudes que activen el inicio del trabajo cron, especialmente si está usando un complemento de almacenamiento en caché. La mejor opción para descargar esto a un horario más regular es deshabilitar la verificación predeterminada en WordPress y usar crontab .

Primero, para deshabilitar la verificación predeterminada (que puede ayudar un poco con el rendimiento del lado del cliente), agregue lo siguiente a wp-config.php :

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

A continuación, crea una tarea para obtener la página wp-cron.php una vez por minuto para procesar cualquier trabajo en el back-end, desde la línea de comandos ingrese crontab -e y luego agregue una línea que se parece a lo siguiente:

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

Comprueba que DISABLE_WP_CRON no está configurado en tu configuración.

Si falla, intente deshabilitar todos los complementos (excepto el control central, aunque usaría wp-crontrol) y vea si sus trabajos principales funcionan. Si lo hacen, estás experimentando interferencias de complementos en algún lugar.

Del mismo modo, intente cambiar a un tema de veintitantos estándar.

Si ninguno de estos hace alguna diferencia, es probable que se trate de un problema de alojamiento.

    
respondido por el vancoder 04.04.2013 - 19:19

Lea otras preguntas en las etiquetas