Bagaimana cara memastikan bahwa hanya satu wp_cron () yang berjalan pada satu waktu?

9

Saya memiliki sekitar 20 wp_cron()fungsi seperti kode berikut. Hampir semua crons beroperasi setiap jam; beberapa harian.

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
}

Untuk meningkatkan kinerja server, dan agar tidak terus mendapatkan pesan batas server dari perusahaan hosting, saya ingin memastikan bahwa hanya satu cron berjalan pada waktu tertentu ... Apakah mungkin?


Jawaban yang diterima saat ini bagus, tapi saya punya pertanyaan berikut, itu sebabnya saya mulai hadiah untuk pertanyaan ini.

Harap baca jawaban yang diterima pada awalnya.

Mari kita asumsikan Cron 1 berjalan, kode cron2 saya tidak akan berjalan karena kita masih berada di dalam 5 menit atau cron pertama masih berjalan, tetapi karena wp_schedule_event( time(), 'hourly', 'my_task_hook' );berjalan untuk cron2 saya pikir WordPress menganggap cron2 berjalan ..... Jadi pada dasarnya kode kode cron2 tidak pernah berjalan ..... Atau saya salah paham sesuatu?

Akulah Orang yang Paling Bodoh
sumber
Tidak, Anda memahaminya dengan benar. Saya akan memperbarui jawaban saya dengan beberapa solusi untuk masalah Anda ...
Krzysiek Dróżdż

Jawaban:

10

Ya, itu mungkin ...

Dan sejujurnya, seringkali sangat penting untuk melakukan ini ... WP Scheduler terkadang cenderung menyebabkan masalah, ketika tugas cron panjang ...

Jadi bagaimana saya mengatasi masalah ini?

Saya menggunakan Transients API untuk mengimplementasikan semaphores ...

Berikut kodenya:

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' );
}

Mengapa saya menggunakan transien dalam kasus ini? Karena:

  • Mereka adalah bagian dari WP.
  • Mereka mudah digunakan dan efisien.
  • Mereka tidak akan menyebabkan kebuntuan. Katakanlah tugas cron saya dapat terbunuh (beberapa kesalahan dapat terjadi, atau berjalan terlalu lama dan terbunuh, dan sebagainya). Dalam kasus seperti itu tidak akan menghapus semaphore, jadi semua tugas di masa depan tidak akan berfungsi. Menggunakan transien memecahkan masalah ini, karena setelah beberapa saat transient akan dihapus.

Dan bagaimana jika ada banyak tindakan berbeda yang harus dilakukan?

Jadi katakanlah ada banyak tugas cron yang berbeda, yang seharusnya tidak pernah berjalan dalam waktu yang sama, tetapi kami masih ingin semuanya berjalan ...

Jika kami menggunakan solusi dengan semaphore dan hanya menggunakan satu semaphore untuk semua tugas ini, maka beberapa di antaranya mungkin tidak pernah berjalan. Lalu apa yang harus dilakukan?

Dalam hal demikian, Anda harus mengubah pemikiran Anda. Anda tidak memiliki beberapa tugas independen, tetapi ada beberapa tugas yang harus dilakukan. Jadi Anda harus menerapkannya dengan cara ini.

Begitu:

  1. Anda menambahkan beberapa jenis antrian (Anda dapat menggunakan array dan menyimpannya sebagai opsi, atau menambahkan tabel DB khusus).
  2. Anda menggunakan acara per jam WP cron Anda saat ini untuk menambahkan tugas ke antrian.
  3. Anda menambahkan tugas cron WP kedua yang berjalan jauh lebih sering dan "memakan" tugas dari antrian satu per satu. Tugas "pemakan" ini harus menggunakan semaphore untuk memastikan bahwa hanya satu tugas yang berjalan pada suatu saat.
Krzysiek Dróżdż
sumber
Terima kasih, tapi saya minta maaf, saya tidak pernah menggunakan transient sebelumnya ... Tapi saya tring untuk memahami kode. Mengapa Anda menetapkan 5 menit untuk sementara karena Anda menghapus sementara menggunakan delete_transient(). Jadi waktu itu penting? Maksud saya, kapan saja Anda menaruh set_transient, itu dihapus setelah pekerjaan saya selesai ... Jadi mengapa ada waktu?
Saya Orang yang Paling Bodoh
Karena beberapa kesalahan dapat terjadi. Lihatlah poin terakhir.
Krzysiek Dróżdż
Terima kasih, bagus ... Hanya satu pertanyaan. Seperti yang saya pahami, Jika saya menggunakan my_task_function_semaphorenama transient, saya harus menggunakan semua crons lain dengan nama yang sama?
Saya Orang yang Paling Bodoh
@IamtheMostStupidPerson itu tergantung pada apa yang ingin Anda capai ... Jika hanya satu tugas yang harus bekerja pada saat tertentu, maka ya - semua tugas harus menggunakan nama transien yang sama dengan semaphore
Krzysiek Dróżdż
1
Saya telah melakukan hal serupa dengan alat Antrian Kerja seperti Gearman. Implementasi ini dapat membantu: github.com/10up/WP-Minions
Fayaz