WP Cron não executa quando o tempo passa

15

O objetivo

Eu quero usar wp_schedule_single_event( ) para executar um único evento que me envia um e-mail 8 minutos após o usuário enviar um formulário.

O problema

O código a seguir está no meu 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 ) );
}

E o seguinte código é usado para chamar schedule-event :

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

Depois de esperar mais de 8 minutos, não havia um e-mail na minha caixa de entrada.

O que eu tentei

Com o Core Control do plugin, é possível ver quais agendamentos estão agendados.

Depoisdealgumasalterações,conseguicorrigi-lase,melhor,quandotoqueiem"Executar agora", recebi um e-mail na minha caixa de entrada.

Mas por que o cron não é executado quando eu visito meu site depois de 8 minutos. O que possivelmente está errado com este código? Eu tenho que dizer que esta é minha primeira vez usando o WP Cron.

tentei mais

Após o comentário do vancoder id, decidi testar se o código funciona se eu colocar o seguinte código diretamente no 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'];
  }
}

A desvantagem deste código é que o usuário precisa ir para outra página antes que esse código seja executado. Mas do outro lado, isso também não funciona, então esse não seria meu primeiro problema ...

    
por Mike Madern 27.03.2013 / 16:12

4 respostas

8

Primeiro, você pode confirmar que não tem nenhum plug-in de cache ativado? Os plug-ins de cache podem interferir nos trabalhos agendados porque seus visitantes não recebem uma página ativa, mas uma versão em cache de sua página.

Se você tiver um plug-in de armazenamento em cache ativado, poderá escolher uma das suas páginas, adicionar uma exclusão às configurações do seu plug-in de armazenamento em cache para essa página, para que nunca seja armazenada em cache.

Em seguida, você terá que criar manualmente uma tarefa cron (usando o cpanel se estiver em um ambiente de hospedagem compartilhada ou do terminal, se for um servidor VPS / dedicado), que visitará essa página a cada alguns minutos.

Espero que ajude!

    
por WPMU-DEV Ari 05.04.2013 / 16:59
13

Primeiramente, defina seus agendamentos de trabalho personalizados do cron.

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

Você precisa decidir onde e quando realmente agendar o evento.

Aqui está apenas um trecho de código, que faz uma chamada para um método de classe 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.
));

Aqui está o código que realmente agenda o 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;
}

Agora, tudo o que você precisa fazer é fazer uma chamada para o nome de sua tarefa Cron personalizada. Neste exemplo, o nome da tarefa cron é custom_imap_import .

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

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

Portanto, neste exemplo, $this->do_imap_import(); é chamado a cada 30 minutos (supondo que você tenha tráfego suficiente no seu site).

Notas

Requer uma visita a uma página para que seu cron seja acionado nos horários corretos.

Exemplo: Se você agendou uma tarefa em intervalos de 30 minutos, mas ninguém visita seu site por 4 horas, seu trabalho no cron não será acionado até que o visitante acesse seu site quatro horas depois . Se você realmente precisa que sua tarefa seja disparada a cada 30 minutos, é aconselhável configurar um cron job legítimo através do seu provedor de hospedagem na web para visitar seu site nos intervalos desejados.

O cron do WordPress não faz seu site ficar lento!

Talvez você esteja pensando e se o script cron demorar muito para ser executado, os visitantes terão que esperar até que o script seja executado. Não! Como isso pode ser possível? Se você olhar para o arquivo wp-cron.php , encontrará uma linha

ignore_user_abort(true);

É uma configuração de php.ini que define que, se você parar de carregar o site / script, o script não parará de ser executado.

Se você olhar para o arquivo wp-includes/cron.php , encontrará uma linha como esta:

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

Isso significa que o WordPress irá esperar apenas 0.01 segundos para acionar a execução e, em seguida, será cancelado, mas como você definiu ignore_user_abort para true , o script estará sendo executado. Essa funcionalidade é uma grande vantagem para executar scripts grandes em tarefas agendadas do WordPress.

Funções disponíveis para ajuda:

por Michael Ecklund 04.04.2013 / 16:22
3

O WordPress Cron permite agendar tarefas, mas elas só serão executadas se houver uma solicitação feita ao site. Para cada solicitação que o WordPress recebe, ele verifica se há tarefas agendadas a serem processadas e, em caso afirmativo, dispara uma solicitação para /wp-cron.php?doing_wp_cron de forma assíncrona para processar o trabalho. Se o início agendado de um trabalho passar sem uma solicitação, o processo do cron não será iniciado.

Como você pode ver e executar seus trabalhos agendados, é possível que não haja solicitações que acionem a tarefa cron para iniciar, especialmente se você estiver usando um plug-in de armazenamento em cache. A melhor opção para descarregar isso para uma programação mais regular é desabilitar a verificação padrão no WordPress e usar crontab .

Primeiro, para desativar a verificação padrão (que pode ajudar um pouco no desempenho do lado do cliente), adicione o seguinte a wp-config.php :

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

Em seguida, crie uma tarefa para buscar a página wp-cron.php uma vez por minuto para processar qualquer tarefa no back-end, na linha de comando, insira crontab -e e adicione uma linha como a seguinte:

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

Verifique se DISABLE_WP_CRON não está definido na sua configuração.

Caso contrário, tente desabilitar todos os plugins (exceto o controle do núcleo - embora eu use o wp-crontrol) e veja se suas tarefas principais funcionam. Se o fizerem, você está experimentando a interferência do plugin em algum lugar.

Da mesma forma, tente mudar para um tema padrão de vinte e poucos anos.

Se nada disso fizer diferença, é provável que seja um problema de hospedagem.

    
por vancoder 04.04.2013 / 19:19