Как убедиться, что одновременно работает только один wp_cron ()?

9

У меня есть около 20 wp_cron()функций, таких как следующий код. Почти все кроны бегают ежечасно; несколько ежедневно.

if ( ! wp_next_scheduled( 'my_task_hook' ) ) {
  wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}

add_action( 'my_task_hook', 'my_task_function' );

function my_task_function() {
  //Complex Code
}

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


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

Пожалуйста, сначала прочитайте принятый ответ.

Предположим, что Cron 1 работает, Мой код cron2 не будет работать, потому что мы все еще находимся в течение 5 минут, или первый cron все еще работает, но из-за wp_schedule_event( time(), 'hourly', 'my_task_hook' );работы для cron2 я думаю, что WordPress считает, что cron2 работает ..... Так что в основном код кода cron2 никогда не запускается ..... Или я что-то неправильно понял?

Я самый глупый человек
источник
Нет, вы правильно поняли. Я обновлю свой ответ некоторыми решениями для вашей проблемы ...
Krzysiek Dróżdż

Ответы:

10

Да, это возможно...

И, честно говоря, это часто очень важно сделать ... WP Scheduler иногда вызывает проблемы, когда задачи cron длинные ...

Так как же мне решить эту проблему?

Я использую Transients API для реализации семафоров ...

Вот код:

if ( ! wp_next_scheduled( 'my_task_hook' ) ) {
  wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}

add_action( 'my_task_hook', 'my_task_function' );

function my_task_function() {
  // if some other my_task is already running, stop
  if ( get_transient( 'my_task_function_semaphore' ) ) return;

  // set semaphore for 5 minutes
  set_transient( 'my_task_function_semaphore', true, 5*60 );

  // DO YOUR STUFF

  delete_transient( 'my_task_function_semaphore' );
}

Почему я использую переходные процессы в этом случае? Потому что:

  • Они являются частью WP.
  • Они просты в использовании и эффективны.
  • Они не вызовут тупиков. Допустим, моя задача cron может быть убита (может произойти какая-то ошибка, или она выполняется слишком долго и будет убита, и так далее). В этом случае он не удалит семафор, поэтому все будущие задачи не будут работать. Использование переходных процессов решает эту проблему, потому что через некоторое время переходные процессы будут удалены.

А что если есть много разных действий?

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

Если мы используем решение с семафором и используем только один семафор для всех этих задач, то некоторые из них могут никогда не запуститься. Так что же делать тогда?

В таком случае вы должны изменить свое мышление. У вас нет независимых задач, но есть очередь задач. Таким образом, вы должны реализовать это таким образом.

Так:

  1. Вы добавляете какую-то очередь (вы можете использовать массив и сохранить его как опцию или добавить собственную таблицу БД).
  2. Вы используете текущее почасовое событие WP cron для добавления задач в очередь.
  3. Вы добавляете вторые задачи WP cron, которые выполняются намного чаще и по очереди "съедают" задачи из очереди. Эта задача «пожирателя» должна использовать семафор, чтобы гарантировать, что в данный момент выполняется только одна задача.
Krzysiek Dróżdż
источник
Спасибо, но я извиняюсь, я никогда не использовал переходный процесс раньше ... Но я пытаюсь понять код. Почему вы установили 5 минут для переходного процесса, потому что вы удаляете переходный процесс, используя delete_transient(). Так что время имеет значение? Я имею в виду, какое время вы добавляете set_transient, оно удаляется сразу после того, как моя работа закончена ... Так почему же есть время?
Я самый глупый человек
Потому что могут возникнуть некоторые ошибки. Посмотрите на последнюю точку пули.
Krzysiek Dróżdż
Спасибо, отлично ... Только один вопрос. Как я понимаю, если я использую my_task_function_semaphoreв качестве имени для переходного процесса, я должен использовать все другие кроны с тем же именем?
Я самый глупый человек
@IamtheMostStupidPerson это зависит от того, чего вы хотите достичь ... Если только одна задача должна работать в данный момент, тогда да - все задачи должны использовать одно и то же временное имя, что и семафор
Krzysiek Dróżdż
1
Я делал подобные вещи с инструментами Job Queue, такими как Gearman. Эта реализация может помочь: github.com/10up/WP-Minions
Фаяз,