큐를 처리하기 위해 cron 태스크가 필요합니까?


32

완료하는 데 약 45 분이 걸리고 매일 발생 해야하는 작업이 있습니다 (사용자를 여러 외부 데이터베이스에 동기화하는 등).

작업을 처리하기 위해 hook_cron_queue_info()다음과 같이 cron 대기열을 설정했습니다 .

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

이 기능을 사용하여 대기열을 채 웁니다.

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

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

대기열 채우기 기능은 cron 작업으로 호출됩니다. 나는 Elysia Cron을 사용 하므로 구현 hook_cronapi()은 다음과 같습니다.

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

에 정의 된 각 대기열 항목의 작업자 기능 mymodule_cron_queue_info은 다음과 같습니다.

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

내 질문은 언제 cron이 실제로 대기열 처리를 시작합니까?

매일 오전 3시에 대기열을 채우고 완료 될 때까지 30 분마다 120 초 동안 처리하려고한다고 가정합니다. 다른 크론 작업을 만들어야합니까?


Drupal 7을 사용하고 있다고 언급해야합니다.
joe_flash

1
이 질문에 대해서도 궁금합니다. 예 또는 아니오를 듣고 싶습니다. 우리는 D7 프로젝트 중 하나에서 큐 API를 많이 사용합니다. 시각적으로 cron이 실행될 때 {queue} 테이블 행이 지워지는 것을 보았습니다. 예라고 가정하십시오.
Sivaji

답변:


19

Drupal은 cron 태스크를 실행할 때 모듈에서 정의 된 모든 cron 큐를 자동으로 처리합니다 drupal_cron_run(). 첫 번째 hook_cron()구현이 호출 된 다음 cron 큐가 비워집니다.

구현 hook_cronapi()하면 모듈의 cron 대기열을 처리하는 다른 함수에 대한 항목을 추가 할 수 있습니다.

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

대안은 Drupal이 크론 대기열을 처리하도록하는 것이지만 Drupal cron 작업이 실행될 때 발생합니다. 모듈의 cron 대기열을 더 자주 비우려면 Elysia Cron 모듈이 처리하는 새로운 cron 작업 만 추가 할 수 있습니다.

Elysia Cron 모듈은 cron 대기열을 처리합니다 elysia_cron_run(). 이 함수는 elysia_cron_cron()(의 구현 hook_cron()), drush_elysia_cron_run_wrapper()(Drush 명령 콜백) 및 자체 cron.php 에서 호출 됩니다. 당신이의 지시에 따른 경우 INSTALL.TXT의 파일 (에 특히 "를 B 단계 : 변경 시스템의 crontab (선택 사항)")과의 호출 교체 http://example.com/cron.php을에 http : // 예 .com / sites / all / modules / elysia_cron / cron.php 에서 Elysia Cron 모듈은 이미 cron 대기열을 처리하고 있어야합니다. 내가 제안한 코드는 효과적으로 수행 해야하는 경우 모듈에서 사용되는 cron 대기열 처리 속도를 높이는 데 사용될 수 있습니다.

// 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();
  }
}

아, 감사합니다 @kiam! 그것이 내가 의심했던 것인데, 나는 내 뇌를 감싸지 못했습니다.
joe_flash

사실, 여기에 뭔가 빠진 것 같습니다. 당신은 대안이 Drupal이 나를 위해 크론 대기열을 처리하게한다고 말했습니다. 내 원래 질문의 일부는 실제로 언제 발생 합니까? crontab이 요청할 때마다 cron.php? 그렇다면 1 분마다 발생합니다 (@David의 회신에 대한 첫 번째 의견 참조).
joe_flash

1
Elysia cron은 elysia_cron_runElysia의 cron.php가 요청 될 때마다 cron 큐가 자동으로 처리되는 자체 cron_queue 프로세서 구현을 가지고있는 것으로 보입니다 .
David Thomas

@joe_flash 죄송합니다 : 더 명확해야합니다. 예, Drupal은 cron.php가 호출 될 때 cron 작업을 실행합니다 (Drupal 7까지 모든 Drupal 버전마다). Drupal 8에서 cron.php는 더 이상 존재하지 않으며 cron 작업은 다른 시스템 경로를 사용하여 실행됩니다.
kiamlaluno

2

대기열은 설정된 시간에 Elysia cronapi 후크를 통해 채워집니다.

그러나 표준 Drupal cron 실행이 발생할 때마다 큐가 처리됩니다.

코어 끝에서 다음 작업자 콜백 처리 스 니펫을 참조하십시오. 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, 아마도 Elysia가 여기에 약간의 합병증을 소개합니까? 저는 매 분마다 Elysia cron.php스크립트 를 트리거하도록 crontab을 설정했습니다 .이를 통해 Elysia는 분 단위의 해결로 작업 시간을 제어 할 수 있습니다. 실제로 매분마다 작업이 실행되지 않습니다. 대기열에서 특별히 작업하기 위해 작업을 만들어야한다고 생각한 이유는 무엇입니까?
joe_flash

@joe_flash drupal_cron_run는 호출되는 동안 cron 큐 작업자 콜백이 처리됩니다.
David Thomas

아, 네 말이 맞아 그러나 drupal_cron_runElysia cron.php스크립트 에서 호출되지 않습니다 (Elysia가 활성화 된 경우). elysia_cron_run대신 사용됩니다.
joe_flash

이 경우 위의 hook_cron_queue_info핵심 drupal_cron_run함수 스 니펫에 따라 자체 작업자 콜백을 지정하지 않으면 Elysia cron과 함께 사용할 수없는 것 같습니다 .
David Thomas

elysia_cron_run호출하지 않습니다 drupal_cron_run, 그러나 그것은 않습니다 전화를 module_invoke_all('cron_queue_info')몇 가지 팬시 팬츠 차종 내 귀를 나오는 연기 것을 처리하는 멀티 채널 및 않습니다.
joe_flash

1

Elysia Cron을 사용할 때 위에서 언급 한대로 대기열이 처리되지 않습니다.

drupal_run_cron에서 실행되는 큐에 대한 액세스 권한이없는 사용자 (및 drupal)

해결 방법은 모든 대기열 또는 원하는 대기열을 처리하고 대기열 처리를 호출하는 사용자 정의 cron 작업 (Elysia Cron에 표시됨)을 작성하는 것입니다. 즉 :

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

이제 대기열 처리는 ElysiaCron에 의해 제어 될 수 있습니다


0

나는 Elysia를 사용하지 않지만 내 솔루션은 항상 다음과 같습니다.

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

각 cron 실행마다 하나의 항목 만 처리합니다. 어쩌면 당신은 그것을 바꾸고 싶을 것입니다.


0

나는 또한 Elysia cron과 함께 Queue API를 처음 사용하기 때문에 머리를 감싸려고 노력했습니다. 자세히 살펴보면 elysia_cron_run 함수 가 호출 될 때 Elysia cron이 대기열 항목을 실행 함을 알 수 있습니다 . elysia_cron.module 파일의 1044 행에있는 이 스 니펫을 참조하십시오 .

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

이것은 Elysia cron을 사용할 때 대기열 처리를 미 신화하는 데 도움이되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.