WP Cron não executa quando o tempo passa

16

O objetivo

Eu quero usar wp_schedule_single_event( )para executar um único evento que me envia um email 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 email na minha caixa de entrada.

O que eu tentei

Com o plugin Core Control , é possível ver quais tarefas do cron estão agendadas.

Tela de controle principal

Depois de algumas alterações, eu consegui corrigi-las de maneira correta e, melhor, ao clicar em "Executar agora", recebo um e-mail na minha caixa de entrada.

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

Eu 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 desse código é que o usuário precisa ir para outra página antes que esse código seja executado. Mas, por outro lado, isso também não funciona, de modo que não seria meu primeiro problema ...

Mike Madern
fonte
11
Onde e como é schedule_event( $_SESSION['insert_id'] );demitido?
vancoder
Um código abreviado inclui um arquivo separado (com um formulário) em uma página. Quando esse formulário é publicado, a página é recarregada, o mesmo arquivo é executado e schedule_event( ), digamos, no topo do arquivo incluído carregado pelo código abreviado.
quer
Fazer qualquer crons trabalho? wp_version_check etc?
vancoder
Eu não consegui nenhum cron para trabalhar. Qual poderia ser o problema disso?
Mike Madern 29/03
Para confirmar - até mesmo os trabalhos principais do cron falham?
precisa saber é o seguinte

Respostas:

8

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

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

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

Espero que ajude!

WPMU-DEV Ari
fonte
Eu tenho um plugin de cache ativado! W3 Total Cache para ser mais preciso
Mike Madern
14

Em primeiro lugar, defina seus agendamentos de tarefas 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;
}

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

Aqui está apenas um exemplo de 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 é chamar o nome da 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 para o seu site).


Notas

Requer uma visita à 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 visitou seu site por 4 horas, seu trabalho cron não será acionado até que esse visitante chegue ao seu site quatro horas depois. Se você realmente realmente precisa que sua tarefa seja executada a cada 30 minutos, é aconselhável configurar um trabalho cron legítimo através do seu provedor de hospedagem para visitar seu site nos intervalos desejados.

Os trabalhos cron do WordPress não tornam seu site lento!

Talvez você esteja pensando que, se o cron-script 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 wp-cron.phparquivo, encontrará uma linha

ignore_user_abort(true);

É uma php.iniconfiguração que define que, se você parar de carregar o site / script, o script não interromperá a execução.

Se você olhar para o wp-includes/cron.phparquivo, 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 WordPress irá esperar apenas 0,01 segundo para desencadear a execução, em seguida, ele irá abortar, mas como você definiu ignore_user_abortpara trueo script será executado. Essa funcionalidade é uma grande vantagem para executar scripts grandes em tarefas cron do WordPress.

Funções disponíveis para auxílio:

Michael Ecklund
fonte
6
Essa é uma resposta notavelmente abrangente, que, até onde eu posso ver, falha ao abordar a questão real - e é por isso que todas as tarefas agendadas (incluindo as principais tarefas) falham.
vancoder
Esta resposta é para orientar o usuário na direção certa para entender e agendar corretamente as tarefas cron do WordPress.
Michael Ecklund
4
Isso com certeza me ajudou muito compreensão horários cron com WordPress
Mike Madern
2
Michael, você deve responder com mais frequência. Ótimo +1
kaiser 03/10
11
Eu acho que WP_Cronusa GMT sob o capô, como o resto do WP, então seria melhor agendar o primeiro evento em time()vez de current_time().
Ian Dunn
3

O WordPress Cron permite que você agende tarefas, mas elas serão executadas apenas se houver uma solicitação ao site. Para cada solicitação que o WordPress recebe, ele verifica se há tarefas agendadas para processar e, em caso afirmativo, dispara uma solicitação de /wp-cron.php?doing_wp_cronforma assíncrona para processar a tarefa. Se o início agendado de um trabalho for aprovado sem uma solicitação, o processo cron não será iniciado.

Como você pode ver e executar seus trabalhos agendados, é possível que não haja solicitações que iniciem o trabalho cron, especialmente se você estiver usando um plug-in de cache. A melhor opção para transferir isso para uma programação mais regular é desativar a verificação padrão no WordPress e usá-la crontab.

Primeiro para desativar a verificação padrão (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, você cria uma tarefa para buscar a wp-cron.phppágina uma vez por minuto para processar qualquer trabalho no back-end, na linha de comando, digite crontab -ee adicione uma linha parecida com a seguinte:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
doublesharp
fonte
2
Se você não atribuir um valor a doing_wp_cron, é altamente provável que algumas vezes os trabalhos sejam executados duas vezes. Use doing_wp_cron=$(date +\%s.\%N)para evitar isso.
Alexander Garden
0

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

Caso contrário, tente desativar todos os plug-ins (exceto o controle principal - embora eu use o wp-crontrol) e verifique se seus trabalhos principais funcionam. Se o fizerem, você está tendo interferência de plug-ins em algum lugar.

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

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

vancoder
fonte
Eu não tenho DISABLE_WP_CRONdefinido na minha wp-config.php, vou tentar mais coisas e voltar mais tarde
Mike Madern
0

Verifique qualquer plugin que oculte o Wordpress.

Como ver se esse é o problema?

  1. Navegue para http (s): //seu site.com/wp-cron.php Você deverá ver uma página vazia. Um completamente vazio.
  2. Além disso, você deve ver em um gerenciador de tarefas cron um horário em "Próxima execução": Trabalho programado - se o wp-cron.php funcionar corretamente (não apenas o texto "Na fila" - mas um determinado período de tempo - para algumas entradas "Na fila" está bom algumas vezes, mas se é a única coisa você vê -> seu cron não funciona.)

+1. Não acredite em nenhum plug-in que "verifique se o cron está funcionando" - por exemplo, o plug-in do verificador de status do WP Cron mostrou que o cron está funcionando. Mas na verdade não. O que quer que seja mostrado - acredite nos seus olhos e não neste plugin!

Conclusão: Se for um erro 404 - desligue a) não apenas os plugins de cache, como outros sugerem b), mas também os plugins que ocultam o Wordpress.

Peter Cz
fonte