Регулярные операции

Cron (регулярные операции) — периодически выполняемые процессы описываемые инструкциями в crontab.

Drupal по умолчанию поддерживает работу с кроном разными способами, а также позволяет разработчикам выполнять свои действия и операции в процессе его вызова.

Настройки Cron

Вы можете найти настройки регулярных операций по пути: Конфигурация - Система - Cron (/admin/config/system/cron).

На данной странице вы можете увидеть информацию о последнем запуске операций, отредактировать некоторые настройки (может меняться в зависимости от профиля и активных модулей), увидить специальную ссылку для запуска крона.

По умолчанию, Drupal предоставляет всего одну настройку — «Подробное логирование крон», которая включена по умолчанию в стандартном профиле. При активации данной настройки, в журнал логов будет записываться, какие хуки регялурных были запущены и сколько было затрачено времени на их выполнение. Drupal также логирует каждый запуск регулярных операций, независимо от данной настройки.

Запуск регулярных операций

Запуск регулярных операций может быть произведён различными способами.

Ручной запуск операций

Данный вариант подразумевает что вы запускаете выполнение регулярных операций путём нажатия кнопки «Запустить cron» на странице настроек. В таком случае запуск будет произведён сразу же не зависимо от других вариантов. Если крон операции уже выполняются, то ничего запущено не будет.

Запуск при помощи URL

При установке сайта, Drupal автоматически генерирует специальный URL в формате https://example.com/cron/{secret_key}, где {secret_key} — случайно сгенерированная строка. Этот URL уникален для каждой новой инсталяции Drupal.

Предупреждение

Не раскрывайте данный URL третьим лицам, так как зная его, можно делать незапланированные вызовы регулярных операций, что может привести к повышенной нагрузке и снижению производительности.

При отправке запроса на данный URL, любым из способов, будет запущено выполнение регулярных операций.

Данный URL можно добавить в системный crontab на вызов, например, через curl или wget.

Пример вызова крон операций при помощи curl:

curl -s {cron_url}

Пример вызова крон операций при помощи wget:

wget --spider {cron_url}

Automated Cron

В поставке Drupal имеется стандартный модуль Automated Cron, который производит запуск регулярных операций в момент обращения к сайту. Данный модуль включен по умолчанию в стандартном установочном профиле.

Он добавляет дополнительную настройку, где вы можете выбрать переодичность запуска крон операций данным способом: Никогда, 1 час, 3 часа, 6 часов, 12 часов, 1 день, 1 неделя.

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

Данный способ рекомендуется использовать если у вас нет иных способов запуска регулярных операций, либо его хватает на текущий момент.

К его недостаткам можно отнести:

  • Вы не можете менять заданные интервалы. Если хотите запускать регялурные операции таким способом каждые полчаса или минуту, то вам уже придётся в ручном режиме корректировать конфигурацию automated_cron.settings:interval или менять форму настроек с предоставлением своих вариантов, иначе настройки будут каждый раз слетать.
  • Операции выполняются после того как запрос отправлен пользователю, но всё в том же процессе, из-за чего он ограничен настройками PHP. Например, если у вас стоит max_execution_time равным 30 (секунд), запрос обработался и вернулся пользователю за 1 секунду, то у крон операций остаётся 29 секунд на выполнение. Если у вашего сайта там имеются тяжелые и длительные операции, это неудачный вариант.
  • Запуск будет производиться только если у сайта есть трафик. Например, если вы выберите запуск каждый час, но на сайт никто не заходил два часа и более, то и запуск операций не будет произведён пока к сайту не произойдёт обращение.
  • Текущий пункт, следствие предыдущего, — непостоянство. Данный вид запуска регулярных операций непостоянен из-за принципа его работы, он не гарантирует точных запусков и соблюдения интервалов. Это может быть критично для некоторых проектов, которые опираются на регулярные операции. Например, если вы хотите генерировать прайс лист каждый час в регулярных операциях — данный метод запуска совершенно не гарантирует актуальность данных в момент их запроса.

Запуск при помощи Drush

Вы можете использовать Drush для запуска крон операций при помощи команды drush cron

Выполнение собственных регулярных операций

Если вы хотите выполнять какие-то действия на сайте при вызове регулярных операций, вам необходимо реализовать хук hook_cron() в .module файле вашего модуля.

Данный хук ничего не принимает и ничего не должен возвращать, вы выполняете то, что вам нужно.

Пример:

/**
 * Implements hook_cron().
 */
function hook_cron() {
  // Short-running operation example, not using a queue:
  // Delete all expired records since the last cron run.
  $expires = \Drupal::state()->get('mymodule.last_check', 0);
  \Drupal::database()->delete('mymodule_table')
    ->condition('expires', $expires, '>=')
    ->execute();
  \Drupal::state()->set('mymodule.last_check', REQUEST_TIME);

  // Long-running operation example, leveraging a queue:
  // Queue news feeds for updates once their refresh interval has elapsed.
  $queue = \Drupal::queue('aggregator_feeds');
  $ids = \Drupal::entityTypeManager()->getStorage('aggregator_feed')->getFeedIdsToRefresh();
  foreach (Feed::loadMultiple($ids) as $feed) {
    if ($queue->createItem($feed)) {
      // Add timestamp to avoid queueing item more than once.
      $feed->setQueuedTime(REQUEST_TIME);
      $feed->save();
    }
  }
  $ids = \Drupal::entityQuery('aggregator_feed')
    ->condition('queued', REQUEST_TIME - (3600 * 6), '<')
    ->execute();
  if ($ids) {
    $feeds = Feed::loadMultiple($ids);
    foreach ($feeds as $feed) {
      $feed->setQueuedTime(0);
      $feed->save();
    }
  }
}

Если то что вы делаете в регулярных операциях требует мало времени, вы можете оставить эту операцию прямо в хуке. Если же ваша операция требует много времени, рекомендуется использовать механизм очередей. Для этого объявите свой Queue Worker и наполняйте его задачами из регулярных операций. Queue Worker автоматически вызываются в конце выполнения всех регулярных операций на каждый крон.

Решение проблем

Какой способ запуска предпочтительный?

Исходя из перечисленных выше вариантов запуска регулярных операций, их можно расположить в следующему порядке, от лучшего к худшему:

  • Запуск при помощи CLI, например Drush.
  • Запуск при помощи вызова специального URL системным кроном.
  • Automated Cron
  • Ручной запуск

Конечный выбор сильно зависит от проекта и того, какие задачи решаются регулярными операциями. Также, выбор зависит от того, какой из вариантов вы можете использовать, если вы пользуетесь хостингом. С первыми двумя могут быть сложности, тогда как последние два заработают в любом случае, и, фактически, являются резервными.

Преимущество CLI вызова в том, что, как правило, CLI операции имеют меньше ограничений на ресурсы и время выполнения, а следовательно, операции выполнятся быстрее и с большей вероятностью (если они длительные). Также, CLI вызов происходит напрямую через вызов Drupal API, тогда как вызов через URL или Automated Cron также вовлекают в процесс веб-сервер (nginx, Apache), что может, также, добавить проблем и сложностей. Например, max_execution_time для PHP равен 60 секундам, а таймаут на запрос веб-сервера (nginx, Apache) 30 секунд. В таком случае, если регулярные операции не уложатся в 30 секунд, веб-сервер прервёт обработку запроса и закроет PHP процесс отвечающий за него, что может привести к сбою данных.

В результатах выполнения вместо адреса сайта стоит default

Если в результате выполнения регулярных операций в результирующем файле вместо настоящего домена стоит http://default/, вероятнее всего вы используете Drush.

Так как вызов из CLI происходит не через веб-запрос, Drupal не знает домен с которого происходит обработка и берёт в качестве значения название сайта по умолчанию, который является default.

Для того чтобы решить данную проблему, в вызов drush cron необхдимо также передать опцию --uri с корректным адресом вашего сайта.

Пример:

drush cron --uri=https://example.com

Вы также можете задать данное значение в конфигурационном файле Drush для вашего сайта.

Ссылки

🌱 Помогите нам сделать документацию лучше!

Вся документация Druki с отрытым исходным кодом. Нашли ошибку или неточность? Создайте pull request.

Редактировать текущий документ Обсудить улучшение

Или узнайте как контрибутить.

🤔 По-прежнему нужна помощь?

Не нашли ответа на свой вопрос? Попросите помощи у сообщества!

Задайте вопрос на GitHub Смотрите другие ресурсы сообщества