web-dev-qa-db-ja.com

一度に1つのwp_cron()のみが実行されるようにする方法は?

次のコードのような約20個のwp_cron()関数があります。ほとんどすべてのcronは1時間ごとに実行されます。いくつかは毎日です。

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
}

サーバーのパフォーマンスを向上させ、ホスティング会社からサーバー制限メッセージを取得し続けないように、特定の時間に1つのcronのみが実行されるようにします...可能ですか?


現在受け入れられている答えは素晴らしいですが、私は次の質問があります。だから私はこの質問に報いを始めます。

最初に受け入れられた答えを読んでください。

Cron 1が実行され、cron2のコードはまだ5分以内または最初のcronがまだ実行されているため実行されませんが、cron2でwp_schedule_event( time(), 'hourly', 'my_task_hook' );が実行されているため、WordPressはcron2の実行と見なします。 ....つまり、基本的にcron2コードのコードは決して実行されません。

はい、可能です….

正直に言うと、これを行うことが非常に重要です。WP 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つのセマフォだけを使用すると、それらの一部が実行されない可能性があります。それでは何をしますか?

そのような場合、あなたはあなたの考えを変えるべきです。いくつかの独立したタスクはありませんが、実行するタスクのキューがあります。だからあなたはこのようにそれを実装する必要があります。

そう:

  1. ある種のキューを追加します(配列を使用してそれをオプションとして保管することも、カスタムDBテーブルを追加することもできます)。
  2. タスクをキューに追加するには、現在のWP cron時間別イベントを使用します。
  3. もっと頻繁に実行される2番目のWP cronタスクを追加し、それがキューからタスクを一つずつ「食べる」のです。この "イーター"タスクはセマフォを使用して、一度に1つのタスクだけが実行されるようにします。
9