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


9

wp_cron()次のコードのような関数が約20個あります。ほとんどすべての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
}

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


現在受け入れられている答えは素晴らしいですが、私は次の質問を持っています、それが私がこの質問に対する賞金を始める理由です。

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

cron 1が実行されるとしましょう。5分以内にいるため、または最初のcronがまだ実行されているため、cron2のコードは実行されませんが、cron2のためにwp_schedule_event( time(), 'hourly', 'my_task_hook' );実行されているため、WordPressはcron2 が実行されていると見なすと思います。 cron2コードの実行は実行されません。


いいえ、あなたはそれを正しく理解しています。私はあなたの問題に対するいくつかの解決策で私の答えを更新します...
KrzysiekDróżdż

回答:


10

はい、可能です...

正直に言うと、これを行うことが非常に重要になることがよくあります... 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つずつ「食べる」。この「イーター」タスクは、セマフォを使用して、一度に1つのタスクのみが実行されるようにする必要があります。

おかげで、申し訳ありませんが、これまでトランジェントを使用したことはありません...しかし、コードを理解するために努力しています。を使用して一時ファイルを削除したので、なぜ5分間の一時ファイルを設定したのですかdelete_transient()。それで時間が重要ですか?つまりset_transient、あなたがに入れた時間は、私の仕事が終わった直後に削除されます...では、なぜ時間があるのですか?
私は最も愚かな人物です

多少の誤差が生じる場合がございます。最後の箇条書きを見てください。
KrzysiekDróżdż

ありがとう、すばらしい...たった1つの質問。私が理解しているように、my_task_function_semaphoretransientの名前としてを使用する場合、他のすべてのcronを同じ名前に使用する必要がありますか?
私は最も愚かな人です

@IamtheMostStupidPersonそれは達成したいものに依存します...特定の瞬間に1つのタスクのみが機能する場合、はい-すべてのタスクはセマフォと同じ一時的な名前を使用する必要があります
KrzysiekDróżdż

1
Gearmanのようなジョブキューツールでも同様のことを行っています。この実装は、役立つことがあります。github.com/10up/WP-Minions
Fayaz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.