Еженедельный cron либо не имеет расписания, либо срабатывает слишком много раз по пятницам.

Вопрос или проблема

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

function cron_add_weekly( $schedules ) {
  $schedules['everyweek'] = array(
    'interval' => 60 * 60 * 24 * 7, # 60 * 60 * 24 * 7 = 604,800, секунд в неделе
    'display' => __( 'Once Every Week' )
  );
return $schedules;
}
add_filter( 'cron_schedules', 'cron_add_weekly' );
add_action('woocommerce_order_action_clone_order_weekly', 'cronstarter_activation_weekly');
function cronstarter_activation_weekly( $order ) {
  if ( ! is_a($order, 'WC_Order') ) {
    return;
  }

  $order_number = $order->get_order_number();
  $name =  $order->get_billing_company();

  // Передать номер заказа и имя в качестве аргументов
  $args  = array( $order, $order_number, $name );

  if( ! wp_next_scheduled( 'clone_order_weekly', $args ) ) {
    wp_schedule_event(time(), 'weekly', 'clone_order_weekly', $args );
  }
}

И вот функция для активации клонирования:

add_action ('clone_order_weekly', 'trigger_action_clone_order');
function trigger_action_clone_order( $order ) {
  if ( ! is_a($order, 'WC_Order') || $order->get_order_number() == 0 ) {
    return; // Выйти, если это не объект WC_Order или номер заказа равен 0
  }

  // Для тестирования (Отправить электронное письмо с ID заказа)
  $recipients="[email protected]";
  $subject="Запланированная задача Cron из заказа номер #".$order->get_order_number();
  $message="Это тестовое письмо из запланированной задачи Cron по заказу номер #".$order->get_order_number();
  wp_mail($recipients, $subject, $message);

  // Добавить флаг к родительскому заказу
  $order->add_meta_data( '_is_recurring_order', 'true');
  $order->add_meta_data( '_is_recurring_order_weekly_parent', 'true');
  $order->add_meta_data( '_is_recurring_order_child_created', date("d-m-Y H:i:s"));

  $order->save();

  // Создать дочерний заказ (клон родительского заказа)
  $child_order = mutiara_woocommerce_order_clone( $order_id = $order->get_id(), 
  $frequency = 'weekly');

  if ( $child_order && is_a($child_order, 'WC_Order') ) {
    // Получить ID дочернего заказа
    $child_order_id = $child_order->get_id();

    // Сохранить ID дочернего заказа в родительском заказе
    $order->add_meta_data( '_recurring_order_child_id', $child_order_id );
    $order->save();
  }
}

Функция mutiara_woocommerce_order_clone — это логика клонирования. В начале все шло хорошо, затем после обновления WP, клон активируется каждые 2 минуты с клонированием ID заказа 0 (странно, только по пятницам), поэтому в trigger_action_clone_order я добавил дополнительную проверку:

if ( ! is_a($order, 'WC_Order') || $order->get_order_number() == 0 ) {
    return; // Выйти, если это не объект WC_Order или номер заказа равен 0
  }

Это работает, так как больше нет клонирования каждые 2 минуты по пятницам.. но я вижу “Cron missing schedule” и клонирование перестает работать.

В чем может быть проблема? И как я могу это исправить?

Ответ или решение

Проблема, с которой вы сталкиваетесь в вашем WooCommerce-сайте, связана с тем, что ваше запланированное задание cron начинает некорректно работать после обновления WordPress. Запланированное задание cron иногда либо пропускает выполнение, либо срабатывает неправильно, вызывая дублирование идентификатора заказа "0", особенно по пятницам. Эта ситуация делает задачу cron ненадежной, так как она может внезапно перестать работать. Ваш временный обходной путь решает проблему чрезмерного срабатывания, но вводит другую проблему — "Cron missing schedule", и в итоге клонирование заказа останавливается. Рассмотрим более подробно проблемы cron и возможность их решения на основе предоставленного вами кода.

Теория:

Вначале важно понять, как работает система cron в WordPress. WordPress использует псевдо-CRON, который выполняется в зависимости от приобретенных посещений сайта. Это означает, что реальные задачи cron выполняются не в одиночке на сервере, а только когда кто-то посещает ваш сайт, инициируя работу запланированных задач. Существует несколько потенциальных проблем с вашим текущим кодом:

  1. Определение интервала cron: Вы добавили определение крон-интервала "everyweek", но используете его как "weekly". Это несоответствие в имени может вызывать проблемы с планировщиком. Определенный интервал "weekly" может пересекаться с системными событиями и конкурентно срабатывать.

  2. Проблемы с уникальными идентификаторами задачи: В функции wp_schedule_event используется уникальный набор аргументов, передаваемых в cron-задачу. Однако если два события имеют одинаковые аргументы, WordPress может посчитать, что они уже запланированы, и не запустит их вновь. Используя значимые показатели (такие как идентификатор заказа и имя компании) в качестве аргументов, вы избегаете множественных выполнения cron, но это также значит, что одно и то же событие может быть запланировано несколько раз с теми же значениями.

Пример:

Давайте рассмотрим ваш код:

function cron_add_weekly( $schedules ) {
  $schedules['everyweek'] = array(
    'interval' => 60 * 60 * 24 * 7,
    'display' => __( 'Once Every Week' )
  );
  return $schedules;
}
add_filter( 'cron_schedules', 'cron_add_weekly' );

add_action('woocommerce_order_action_clone_order_weekly', 'cronstarter_activation_weekly');
function cronstarter_activation_weekly( $order ) {
  if ( ! is_a($order, 'WC_Order') ) {
    return;
  }

  $order_number = $order->get_order_number();
  $name =  $order->get_billing_company();

  // Pass order number and name as arguments
  $args  = array( $order, $order_number, $name );

  if( ! wp_next_scheduled( 'clone_order_weekly', $args ) ) {
    wp_schedule_event(time(), 'weekly', 'clone_order_weekly', $args );
  }
}

Здесь вы сначала определяете новый интервал ‘everyweek’, но фактически не используете его дальше в коде. Вместо этого в wp_schedule_event вы используете ‘weekly’, который может конфликтовать с другим интервалом, определенным в ядре WP или в стороннем плагине.

Применение:

Чтобы исправить текущие ошибки, предлагаю несколько стратегий:

  1. Исправьте несоответствие в именах интервалов: Убедитесь, что вы согласованно используете ваш новый cron-интервал. Замените все ‘weekly’ в коде на ‘everyweek’, включая вызов wp_schedule_event.

  2. Проверка существования задачи и её очистка: Возможно, устаревшие или "заблокированные" задачи остаются в wp-cron. Чтобы очистить "заблокированные" задачи, вы можете использовать плагин типа WP Crontrol для управления запланированными задачами Cron, что позволит вам удалять или редактировать ошибочные запланированные задачи вручную.

  3. Убедитесь в корректности аргументов запланированных событий: Проверьте, действительно ли аргументы, которые вы передаете (номер заказа, имя компании), уникальны и позволяют системе отслеживать каждое событие как уникальное. Поработайте над исключениями, чтобы избежать использования заказов с идентификатором 0.

  4. Проанализируйте связанную с WooCommerce/WordPress среду: После обновления WordPress или WooCommerce изменения в системе могут вызвать невалидность или некорректное выполнение некоторых функций крон, например, сбои в зависимости от оптимизаций базы данных.

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

Оцените материал
Добавить комментарий

Капча загружается...