Мне нужна задача cron для обработки очереди?

У меня есть задача, которая занимает около 45 минут для завершения и должна выполняться каждый день (синхронизация пользователей с несколькими внешними базами данных и т. д.).

Чтобы справиться с работой, я установил очередь cron с hook_cron_queue_info () следующим образом:

  function mymodule_cron_queue_info () {
  $ queues = array ();
  $ queues ['update_users_queue'] = массив (
    «рабочий вызов» => '_mymodule_process_user_queue_item',
    'time' => 120,
  );
  return $ queues;
}
 

Я заполняю очередь, используя эту функцию:

  function mymodule_queue_all_users_for_synching () {
  //...query для пользователей ...

  $ queue = DrupalQueue :: get ('update_users_queue');
  foreach ($ users as $ user) {
    $ Queue- & GT; CreateItem ($ пользователю);
  }
}
 

Функция заполнения очереди вызывается как задача cron. Я использую Elysia Cron , поэтому моя реализация hook_cronapi () :

  function mymodule_cronapi ($ op, $ job = NULL) {
  $ items = array ();
  $ items ['queue_users_for_synch'] = массив (
    'description' => 'Очередь всех учетных записей пользователей для синхронизации.',
    'rule' => '0 3 * * *', //Запускаем это задание каждый день в 3 часа ночи.
    'callback' => 'Mymodule_queue_all_users_for_synching',
  );
  return $ items;
}
 

Функция employee для каждого элемента очереди, определенная в mymodule_cron_queue_info , выглядит следующим образом:

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

Мой вопрос: , когда cron на самом деле собирается обрабатывать очередь?

Скажем, я заполняю очередь каждый день в 3 часа ночи и хочу обработать ее 120 секунд каждые 30 минут, пока это не будет сделано - Мне нужно создать другую задачу cron?

31 голос | спросил joe_flash 3 Jpm1000000pmThu, 03 Jan 2013 22:59:50 +040013 2013, 22:59:50

5 ответов


17

Когда 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'] = массив (
    'description' => 'Очередь всех учетных записей пользователей для синхронизации.',
    'rule' => '0 3 * * *', //Запускаем это задание каждый день в 3 часа ночи.
    'callback' => 'Mymodule_queue_all_users_for_synching',
  );

  $ items ['clean_queue'] = массив (
    'description' => «Очистите очередь для синхронизации пользователя»,
    'rule' => '0 4 * * *', //Запускаем это задание каждый день в 4 часа ночи.
    'callback' => 'Mymodule_clean_queue',
  );

  return $ items;
}

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

  //Убедитесь, что каждая очередь существует. Нет никакого вреда в попытке воссоздать
  //существующая очередь.
  foreach ($ queues as $ queue_name => $ info) {
    DrupalQueue :: получить ($ queue_name) - & GT; createQueue ();
  }

  foreach ($ queues as $ queue_name => $ info) {
    $ function = $ info ['work callback'];
    $ end = time () + (isset ($ info ['time'])? $ info ['time']: 15);
    $ queue = DrupalQueue :: get ($ queue_name);
    while (time () <$ end & amp; & amp; ($ item = $ queue-> ClaimItem ())) {
      $ Функция ($ item- & GT; данные);
      $ Queue- & GT; DeleteItem ($ пункт);
    }
  }
}
 

Альтернативой является разрешение Drupal обрабатывать очередь cron для вас, но это происходит при выполнении задач Drupal cron. Если вы хотите чаще очищать очередь cron вашего модуля, вы можете добавить новую задачу cron, обрабатываемую модулем Elysia Cron.

Модуль Elysia Cron обрабатывает очереди cron в elysia_cron_run () ; эта функция вызывается из elysia_cron_cron () (реализация hook_cron () ), drush_elysia_cron_run_wrapper () (обратный вызов команды Drush) и из собственного cron.php . Если вы выполнили инструкции в INSTALL.txt (в частности, в« ШАГ В: ИЗМЕНЕНИЕ СИСТЕМЫ CRONTAB (ДОПОЛНИТЕЛЬНО) ») и заменил любое обращение http://example.com/cron.php с http://example.com/sites/all/modules/elysia_cron/cron.php , модуль Elysia Cron должен уже обрабатывать очереди cron. Код, который я предложил, может быть использован для ускорения обработки очередей cron, используемых из вашего модуля, если это действительно необходимо.

  //Этот код является частью кода, выполняемого из модулей /elysia_cron /cron.php.
define ('DRUPAL_ROOT', getcwd ());

include_once DRUPAL_ROOT. '/includes/bootstrap.inc';
drupal_override_server_variables (массив (
  '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 не мог работать, потому что использовался недопустимый ключ.', array (), WATCHDOG_NOTICE);
  drupal_access_denied ();
}
elseif (variable_get ('maintenance_mode', 0)) {
  watchdog ('cron', 'Cron не может работать, потому что сайт находится в режиме обслуживания.', array (), WATCHDOG_NOTICE);
  drupal_access_denied ();
}
else {
  if (function_exists ('elysia_cron_run')) {
    elysia_cron_run ();
  }
  else {
    drupal_cron_run ();
  }
}
 
ответил kiamlaluno 4 Jpm1000000pmFri, 04 Jan 2013 21:35:25 +040013 2013, 21:35:25
2

Очередь будет заселена через крючок Elysia cronapi в установленное время.

Однако очередь будет обрабатываться всякий раз, когда запускается стандартный запуск Drupal cron.

См. этот фрагмент обработки обратного вызова рабочего в конце ядра: ответил David Thomas 4 Jam1000000amFri, 04 Jan 2013 01:02:50 +040013 2013, 01:02:50

1

, как указано выше, при использовании Elysia Cron ваши очереди не обрабатываются.

у вас (и drupal) нет доступа к очередям, которые в противном случае выполнялись бы на drupal_run_cron

Обходной путь заключается в создании пользовательской задачи cron - (это будет видимо для elysia cron) для обработки всех очередей или одного из них, и вызывать обработку очереди там. то есть:

  function mymodule_cron () {
//ниже копируется из drupal_cron_run () в common.inc

//Возьмите определенные очереди cron.
$ queues = module_invoke_all ('cron_queue_info');
drupal_alter ('cron_queue_info', $ queues);

//если вы хотите настроить таргетинг только на одну очередь, вы можете удалить 'foreach'
и ваши $ info = $ queues ['your_queue'];

  foreach ($ queues as $ queue_name => $ info) {
    if (! empty ($ info ['skip on cron'])) {
      //Не запускать, если очередь хочет пропустить.
      Продолжать;
    }
    $ callback = $ info ['work callback'];
    $ end = time () + (isset ($ info ['time'])? $ info ['time']: 15);
    $ queue = DrupalQueue :: get ($ queue_name);
     while (time () <$ end & amp; & amp; ($ item = $ queue-> ClaimItem ())) {
      пытаться {
        call_user_func ($ callback, $ item-> данные);
        $ Queue- & GT; DeleteItem ($ пункт);
      }
      catch (Исключение $ e) {
        //В случае исключения запишите его и оставьте элемент в очереди
        //для последующей обработки.
        watchdog_exception ('cron', $ e);
      }
    }
  }
}
 

теперь обработка очередей может управляться ElysiaCron

ответил masterperoo 10 ThuEurope/Moscow2015-12-10T17:41:14+03:00Europe/Moscow12bEurope/MoscowThu, 10 Dec 2015 17:41:14 +0300 2015, 17:41:14
0

Я не использую Elysia, но мое решение всегда было примерно таким:

  function mymodule_cron () {
  $ queue = DrupalQueue :: get ('mymoudule_queue');
  $ Queue- & GT; createQueue ();
  $ item = $ queue-> requestItem (300);

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

    //Выполнять работу.

    if ($ sucess) {
      $ Queue- & GT; DeleteItem ($ пункт);
      сторожевого пса («mymodule», «Это сработало»);
    }
    else {
      watchdog ('mymodule', 'Это не сработало!', array (), WATCHDOG_ALERT);
    }
  }
}
 

Он обрабатывает только один элемент, для каждого запуска cron. Возможно, вы хотите изменить это.

ответил Martin Poulsen 4 Jpm1000000pmFri, 04 Jan 2013 13:07:19 +040013 2013, 13:07:19
0

Я также пытаюсь обвести вокруг себя эту проблему, поскольку я впервые использую API очереди API вместе с Elysia cron. При ближайшем рассмотрении вы увидите, что Elysia cron выполняет элементы очереди, когда вызывается функция elysia_cron_run . См. Этот фрагмент из строки 1044 в файле elysia_cron.module :

  if (EC_DRUPAL_VERSION> = 7) {
  //Обработка очереди D7
  foreach ($ queues as $ queue_name => $ info) {
    $ function = $ info ['work callback'];
    $ end = time () + (isset ($ info ['time'])? $ info ['time']: 15);
    $ queue = DrupalQueue :: get ($ queue_name);
    while (time () <$ end & amp; & amp; ($ item = $ queue-> ClaimItem ())) {
      $ Функция ($ item- & GT; данные);
      $ Queue- & GT; DeleteItem ($ пункт);
    }
  }
}
 

Это помогло деактивировать обработку очереди для меня при использовании Elysia cron.

ответил Alex Kirsten 17 Jpm1000000pmFri, 17 Jan 2014 14:10:23 +040014 2014, 14:10:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132