Стандартный механизм WP-Cron в WordPress часто вызывает проблемы с производительностью и надежностью запуска запланированных задач, особенно на сайтах с низкой посещаемостью или при высокой нагрузке на сервер. В этой статье мы подробно разберем, как заменить WP-Cron на более надежный и точный механизм отложенного запуска задач с использованием системного cron и собственного кода в WordPress.
Почему стоит отказаться от WP-Cron для запуска задач
В стандартной реализации WP-Cron не является настоящим системным планировщиком задач. Его запуск зависит от посещений сайта: при отсутствии трафика задачи не запускаются вовремя. Это приводит к задержкам в выполнении важных административных процессов, таких как отправка писем, обновление кэша и прочее.
Кроме того, на высоконагруженных сайтах WP-Cron может запускаться слишком часто, создавая дополнительную нагрузку на сервер.
Поэтому для сайтов с критически важными задачами рекомендуется использовать системный cron и отключить WP-Cron.
Отключение WP-Cron и настройка системного cron
Для начала нам нужно отключить встроенный WP-Cron. Для этого в корне WordPress, в файле wp-config.php добавьте следующую строку:
define('DISABLE_WP_CRON', true);
Далее, на сервере нужно создать системное задание cron, которое будет вызывать скрипт запуска задач WordPress с нужным интервалом (например, раз в 5 минут).
Команда для cron может выглядеть так:
*/5 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
Замените https://example.com на URL вашего сайта. Если wget недоступен, можно использовать curl:
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
Такой подход обеспечит регулярный и своевременный запуск задач без зависимости от посещаемости сайта.
Реализация отложенного запуска задач через пользовательский механизм
Иногда необходимо запускать кастомные задачи с более гибкими условиями и контролем. Ниже мы рассмотрим пример реализации собственного отложенного планировщика задач в WordPress без использования WP-Cron.
Создание таблицы для хранения задач
Для надежного хранения задач создадим собственную таблицу в базе данных WordPress. Добавьте следующий код в файл плагина или в functions.php вашей темы:
function wpteam_create_task_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'wpteam_tasks';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
hook VARCHAR(191) NOT NULL,
args TEXT,
run_at DATETIME NOT NULL,
status ENUM('pending', 'running', 'done', 'failed') NOT NULL DEFAULT 'pending',
PRIMARY KEY (id),
INDEX run_at_idx (run_at),
INDEX status_idx (status)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
register_activation_hook(__FILE__, 'wpteam_create_task_table');
Этот код создаст таблицу wp_wpteam_tasks (префикс может отличаться), в которой будут храниться задачи с указанием времени запуска и статуса.
Добавление задач в очередь
Создадим функцию для добавления новых задач в нашу таблицу:
function wpteam_schedule_task($hook, $args = array(), $run_at) {
global $wpdb;
$table_name = $wpdb->prefix . 'wpteam_tasks';
$wpdb->insert(
$table_name,
array(
'hook' => $hook,
'args' => maybe_serialize($args),
'run_at' => $run_at,
'status' => 'pending'
),
array('%s', '%s', '%s', '%s')
);
return $wpdb->insert_id;
}
Пример использования:
wpteam_schedule_task('wpteam_send_reminder_email', array('user_id' => 123), date('Y-m-d H:i:s', strtotime('+10 minutes')));
Обработка и выполнение задач
Создадим скрипт, который будет запускаться по cron и обрабатывать задачи, у которых время запуска наступило или прошло:
function wpteam_run_scheduled_tasks() {
global $wpdb;
$table_name = $wpdb->prefix . 'wpteam_tasks';
$now = current_time('mysql');
// Получаем задачи, которые нужно выполнить
$tasks = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name WHERE status = %s AND run_at <= %s",
'pending', $now
));
foreach ($tasks as $task) {
// Отмечаем задачу как выполняемую
$wpdb->update($table_name, array('status' => 'running'), array('id' => $task->id), array('%s'), array('%d'));
$args = maybe_unserialize($task->args);
// Выполняем задачу, вызывая hook с аргументами
do_action_ref_array($task->hook, array($args));
// Обновляем статус задачи
$wpdb->update($table_name, array('status' => 'done'), array('id' => $task->id), array('%s'), array('%d'));
}
}
// Для запуска из командной строки или через cron
if (defined('WP_CLI') || (php_sapi_name() === 'cli')) {
wpteam_run_scheduled_tasks();
}
Пример задачи: отправка напоминания по email
Добавим обработчик для нашего примера с отправкой email:
add_action('wpteam_send_reminder_email', function($args) {
$user_id = $args['user_id'] ?? 0;
if (!$user_id) return;
$user = get_userdata($user_id);
if (!$user) return;
$to = $user->user_email;
$subject = 'Напоминание от WP-Team';
$message = 'Здравствуйте, это напоминание от вашего сайта.';
wp_mail($to, $subject, $message);
});
Интеграция с системным cron
Чтобы системный cron запускал наши задачи, создайте отдельный PHP-файл в корне сайта, например run-wpteam-tasks.php:
<?php
require_once __DIR__ . '/wp-load.php';
wpteam_run_scheduled_tasks();
И настройте системный cron на запуск этого файла, например:
*/5 * * * * /usr/bin/php /path/to/site/run-wpteam-tasks.php > /dev/null 2>&1
Преимущества и рекомендации
- Наш механизм полностью независим от посещаемости сайта, задачи выполняются точно по расписанию.
- Вы можете создавать задачи с любым набором аргументов и обрабатывать их в своих хуках.
- Хранение задач в базе позволяет контролировать статус и предотвращать повторное выполнение.
- Рекомендуется добавлять логирование ошибок выполнения задач и обрабатывать исключения.
- Для удобства можно расширить функционал, добавив интерфейс управления задачами в админ-панель.
Заключение
Отказ от стандартного WP-Cron в пользу системного cron и собственного механизма отложенного запуска задач значительно повысит надежность и предсказуемость выполнения фоновых процессов на вашем сайте WordPress. Приведенный пример кода можно адаптировать под любые задачи и расширять по мере необходимости.
Для дополнительной оптимизации рекомендуем ознакомиться с плагином Clearfy Pro, который предлагает улучшения производительности и управления задачами в WordPress.