Bir sırayı işlemek için bir cron görevine ihtiyacım var mı?


32

Tamamlanması yaklaşık 45 dakika süren ve her gün yapılması gereken bir görevim var (kullanıcıları birkaç dış veritabanına senkronize etmek, vb.).

İşi yürütmek için hook_cron_queue_info()aşağıdaki gibi bir cron kuyruğu hazırladım :

function mymodule_cron_queue_info() {
  $queues = array();
  $queues['update_users_queue'] = array(
    'worker callback' => '_mymodule_process_user_queue_item',
    'time' => 120,
  );
  return $queues;
}

Bu işlevi kullanarak kuyruğu doldururum:

function mymodule_queue_all_users_for_synching() {
  //...query for users...

  $queue = DrupalQueue::get('update_users_queue');
  foreach($users as $user) {
    $queue->createItem($user);
  }
}

Kuyruk doldurma işlevi cron görevi olarak adlandırılır. Kullandığım Elysia Cron , benim uygulanması böylece hook_cronapi()geçerli:

function mymodule_cronapi($op, $job = NULL) {
  $items = array();
  $items['queue_users_for_synch'] = array(
    'description' => 'Queue all user accounts for synching.',
    'rule' => '0 3 * * *', // Run this job every day at 3am.
    'callback' => 'mymodule_queue_all_users_for_synching',
  );
  return $items;
}

Her kuyruk maddesi için işçi işlevi şöyle tanımlanmıştır mymodule_cron_queue_info:

function _mymodule_process_user_queue_item($item) {
  //...synchronize user ($item)...
}

Sorum şu, cron ne zaman kuyruğu işlemeye başlayacak?

Her gün saat 3'te kuyruğu doldurduğumu ve her 30 dakikada bir 120 saniye işlemek istediğimi ve başka bir cron görevi oluşturmam gerekir mi?


Drupal 7 kullanıyorum.
joe_flash

1
Bu sorular hakkında da merak ediyorum. Evet ya da hayır duymak istiyorum. D7 projelerimizden birinde sıra API'sini yoğun kullanıyoruz. Gördüğüm gibi görüyorum ki {sıra} tablo satırları cron çalıştığında temizlenir. Diyelim ki evet.
Sivaji

Yanıtlar:


19

Drupal cron görevlerini çalıştırdığında, modüllerden tanımlanan cron sırasını otomatik olarak yönetir drupal_cron_run(); ilk hook_cron()uygulamalar başlatılır ve ardından cron sıraları boşaltılır.

Uygulamada hook_cronapi(), modülünüzün cron kuyruğunu ele alan başka bir fonksiyon için bir giriş ekleyebilirsiniz.

function mymodule_cronapi($op, $job = NULL) {
  $items = array();

  $items['queue_users_for_synch'] = array(
    'description' => 'Queue all user accounts for synching.',
    'rule' => '0 3 * * *', // Run this job every day at 3am.
    'callback' => 'mymodule_queue_all_users_for_synching',
  );

  $items['clean_queue'] = array(
    'description' => 'Clean the queue for the user synching.',
    'rule' => '0 4 * * *', // Run this job every day at 4 AM.
    'callback' => 'mymodule_clean_queue',
  );

  return $items;
}

function mymodule_clean_queue() {
  $queues = module_invoke('mymodule', 'cron_queue_info');
  drupal_alter('cron_queue_info', $queues);

  // Make sure every queue exists. There is no harm in trying to recreate an
  // existing queue.
  foreach ($queues as $queue_name => $info) {
    DrupalQueue::get($queue_name)->createQueue();
  }

  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
}

Alternatif, Drupal'ın sizin için cron kuyruğunu yönetmesine izin vermektir, ancak bu Drupal cron görevleri yerine getirildiğinde gerçekleşir. Modülünüzün cron kuyruğunu daha sık boşaltmak istiyorsanız, yalnızca Elysia Cron modülü tarafından yönetilen yeni bir cron görevi ekleyebilirsiniz.

Elysia Cron modülü, içindeki cron sıralarını yönetir elysia_cron_run(); bu işlev elysia_cron_cron()(bir uygulama hook_cron()), drush_elysia_cron_run_wrapper()(bir Drush komutu geri çağırma) ve kendi cron.php'sinden çağrılıyor . Eğer talimatları izlediyseniz INSTALL.txt dosyasında (özellikle "ADIM B: DEĞİŞİM SİSTEMİ CRONTAB (İSTEĞE BAĞLI)") ve herhangi çağırma yerini http://example.com/cron.php ile http: // örnek .com / sites / all / module / elysia_cron / cron.php , Elysia Cron modülünün halihazırda cron kuyruklarını işlemesi gerekir. Önerdiğim kod, etkin bir şekilde yapılması gerekiyorsa, modülünüzden kullanılan cron kuyruklarını işlemeyi hızlandırmak için kullanılabilir.

// This code is part of the code executed from modules/elysia_cron/cron.php.
define('DRUPAL_ROOT', getcwd());

include_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_override_server_variables(array(
  'SCRIPT_NAME' => '/cron.php',
));
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

if (!isset($_GET['cron_key']) || variable_get('cron_key', 'drupal') != $_GET['cron_key']) {
  watchdog('cron', 'Cron could not run because an invalid key was used.', array(), WATCHDOG_NOTICE);
  drupal_access_denied();
}
elseif (variable_get('maintenance_mode', 0)) {
  watchdog('cron', 'Cron could not run because the site is in maintenance mode.', array(), WATCHDOG_NOTICE);
  drupal_access_denied();
}
else {
  if (function_exists('elysia_cron_run')) {
    elysia_cron_run();
  }
  else {
    drupal_cron_run();
  }
}

Ah, teşekkürler @kiam! Şüphelendiğim şey buydu, ama beynimi onun etrafına saramadım.
joe_flash

Aslında sanırım burada bir şeyleri özlüyorum. Alternatifin Drupal'ın benim için cron sırasını idare etmesine izin verdiğini söyledin; Sanırım asıl sorumun bir kısmı bu gerçekten ne zaman olacak ? Crontab her zaman ister cron.phpmi? Bu durumda, bu her dakika olur (@ David'in yanıtıyla ilgili ilk yorumuma bakın).
joe_flash

1
Elysia cron'un kendi cron_queue işlemci uygulamasına sahip olduğu ve Elysia'nın elysia_cron_runcron.php'si her istendiğinde cron kuyruklarının otomatik olarak işlendiği anlaşılıyor.
David Thomas

@joe_flash Üzgünüm: Daha net olmalıydım. Evet, Drupal, cron.php çağrıldığında cron görevlerini çalıştırır (Drupal 7'ye kadar her Drupal sürümü için). Drupal 8'de, cron.php artık mevcut değildir ve cron görevleri farklı bir sistem yolu kullanılarak yürütülür.
kiamlaluno

2

Kuyruk, belirlenen saatte Elysia cronapi kancası ile doldurulur.

Ancak, standart Drupal cron çalışması gerçekleştiğinde kuyruk işlenecektir.

Çekirdeğin sonundaki bu çalışan geri arama işlem pasajına bakın : drupal_cron_run

 foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }

David, belki Elysia, burada biraz karışıklık getirdi? Her dakika Elysia cron.phpsenaryosunu tetiklemek için crontab'ı ayarladım , bu Elysia'nın görev zamanlarını dakika bazında çözünürlükle kontrol etmesine olanak tanır. Gerçekte her dakika hiçbir görev yürütülmüyor - hangisi özellikle sıralar üzerinde çalışmak için bir görev oluşturmam gerektiğini düşündürdü?
joe_flash

@joe_flash drupal_cron_runçağrıldığı sürece , cron kuyruğu çalışanı geri arama işleminiz gerçekleştirilir.
David Thomas

Ah, bence haklısın. Ancak, drupal_cron_runElysia cron.phpsenaryosundan çağrılmaz (Elysia etkinken); elysia_cron_runyerine kullanılır.
joe_flash

Bu durumda, yukarıdaki hook_cron_queue_infoana drupal_cron_runişlev snippet'ine göre kendi işçi geri çağrınızı belirtmediğiniz sürece Elysia cron ile kullanamazsınız gibi görünüyor .
David Thomas

elysia_cron_runçağrı yapmaz drupal_cron_run, ancak does çağrıyı module_invoke_all('cron_queue_info')bazı fantezi-pantolon markaları kulaklarım çıkıp duman olduğunu taşıma çok kanallı ve yapar.
joe_flash

1

Yukarıda Elysia Cron kullanırken belirtildiği gibi, sıralarınız işleme alınmaz.

siz (ve drupal) drupal_run_cron üzerinde çalışan kuyruklara erişemezsiniz

Buradaki çözüm, istediğiniz tüm kuyrukları ya da istediklerinizi işlemek ve orada kuyruk işleme çağırmak için özel bir cron görevi oluşturmaktır (bu, elysia cron'a görünür olacaktır). yani:

function mymodule_cron() {
// below is copied from drupal_cron_run() in common.inc

// Grab the defined cron queues.
$queues = module_invoke_all('cron_queue_info');
drupal_alter('cron_queue_info', $queues);

//if you want to target only one queue you can remove 'foreach'
and your $info = $queues['your_queue'];

  foreach ($queues as $queue_name => $info) {
    if (!empty($info['skip on cron'])) {
      // Do not run if queue wants to skip.
      continue;
    }
    $callback = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
     while (time() < $end && ($item = $queue->claimItem())) {
      try {
        call_user_func($callback, $item->data);
        $queue->deleteItem($item);
      }
      catch (Exception $e) {
        // In case of exception log it and leave the item in the queue
        // to be processed again later.
        watchdog_exception('cron', $e);
      }
    }
  }
}

şimdi sıra işleme ElysiaCron tarafından kontrol edilebilir


0

Elysia kullanmıyorum, ancak çözümüm hep böyle olmuştur:

function mymodule_cron() {
  $queue = DrupalQueue::get('mymoudule_queue');
  $queue->createQueue();
  $item = $queue->claimItem(300);

  if (!empty($item->data)) {

    // Do the work.

    if ($sucess) {
      $queue->deleteItem($item);
      watchdog('mymodule', 'It worked.');
    }
    else {
      watchdog('mymodule', 'It did not work!', array(), WATCHDOG_ALERT);
    }
  }
}

Her cron koşusu için sadece bir eşya kullanır. Belki bunu değiştirmek istersin.


0

Ayrıca sıraya, Elysia cronu ile birlikte ilk kez Queue API kullandığım için kafamı sarmaya çalışıyorum. Yakından incelendikten sonra, elysia_cron_run işlevi çağrıldığında Elysia cronunun kuyruk öğelerini çalıştırdığını görebilirsiniz . Elysia_cron.module dosyasındaki 1044 satırındaki bu kod parçasına bakın :

if (EC_DRUPAL_VERSION >= 7) {
  // D7 Queue processing
  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {
      $function($item->data);
      $queue->deleteItem($item);
    }
  }
}

Bu Elysia cron kullanırken benim için sıra işlemenin ortadan kaldırılmasına yardımcı oldu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.