Wie kann sichergestellt werden, dass jeweils nur ein wp_cron () ausgeführt wird?

9

Ich habe ungefähr 20 wp_cron()Funktionen wie den folgenden Code. Fast alle Cron laufen stündlich; einige sind täglich.

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
}

Um die Serverleistung zu erhöhen und keine Server-Limit-Nachrichten von Hosting-Unternehmen zu erhalten, möchte ich sicherstellen, dass jeweils nur ein Cron ausgeführt wird ... Ist dies möglich?


Die derzeit akzeptierte Antwort ist großartig, aber ich habe folgende Frage, deshalb starte ich ein Kopfgeld für diese Frage.

Bitte lesen Sie zuerst die akzeptierte Antwort.

Nehmen wir an, Cron 1 wird ausgeführt. Mein Code von cron2 wird nicht ausgeführt, da wir uns noch innerhalb der 5 Minuten befinden oder der erste Cron noch ausgeführt wird. Aufgrund der wp_schedule_event( time(), 'hourly', 'my_task_hook' );Ausführung von cron2 denke ich, dass WordPress als cron2 ausgeführt wird. Also im Grunde genommen Code von cron2 Code nie ausgeführt ..... Oder ich habe etwas falsch verstanden?

Ich bin die dümmste Person
quelle
Nein, du verstehst es richtig. Ich werde meine Antwort mit einigen Lösungen für Ihr Problem aktualisieren ...
Krzysiek Dróżdż

Antworten:

10

Ja, es ist möglich...

Und um ehrlich zu sein, ist es oft sehr wichtig, dies zu tun ... WP Scheduler verursacht manchmal Probleme, wenn Cron-Aufgaben lang sind ...

Wie löse ich dieses Problem?

Ich benutze die Transienten-API , um Semaphoren zu implementieren ...

Hier ist der Code:

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

Warum verwende ich in diesem Fall Transienten? Weil:

  • Sie sind Teil von WP.
  • Sie sind einfach zu bedienen und effizient.
  • Sie werden keine Deadlocks verursachen. Angenommen, meine Cron-Aufgabe kann getötet werden (es kann ein Fehler auftreten oder sie läuft zu lange und wird getötet usw.). In diesem Fall wird das Semaphor nicht gelöscht, sodass alle zukünftigen Aufgaben nicht funktionieren. Die Verwendung von Transienten löst dieses Problem, da Transienten nach einiger Zeit gelöscht werden.

Und was ist, wenn es viele verschiedene Aktionen gibt?

Nehmen wir also an, es gibt viele verschiedene Cron-Aufgaben, die niemals zur gleichen Zeit ausgeführt werden sollten, aber wir möchten, dass sie alle ausgeführt werden ...

Wenn wir die Lösung mit Semaphor verwenden und für alle diese Aufgaben nur ein Semaphor verwenden, werden einige von ihnen möglicherweise nie ausgeführt. Was ist dann zu tun?

In diesem Fall sollten Sie Ihr Denken ändern. Sie haben keine unabhängigen Aufgaben, sondern eine Reihe von Aufgaben. Sie sollten es also auf diese Weise implementieren.

So:

  1. Sie fügen eine Art Warteschlange hinzu (Sie können ein Array verwenden und als Option speichern oder eine benutzerdefinierte DB-Tabelle hinzufügen).
  2. Sie verwenden Ihr aktuelles stündliches WP-Cron-Ereignis, um Aufgaben zur Warteschlange hinzuzufügen.
  3. Sie fügen zweite WP-Cron-Aufgaben hinzu, die viel häufiger ausgeführt werden und die Aufgaben einzeln aus der Warteschlange "fressen". Diese "Esser" -Aufgabe sollte ein Semaphor verwenden, um sicherzustellen, dass jeweils nur eine Aufgabe ausgeführt wird.
Krzysiek Dróżdż
quelle
Danke, aber es tut mir leid, ich habe noch nie Transient verwendet ... Aber ich versuche den Code zu verstehen. Warum haben Sie 5 Minuten Zeit für transiente eingestellt , weil Sie die transiente löschen verwenden delete_transient(). Also ist diese Zeit wichtig? Ich meine, wann immer Sie set_transientes tun, es wird gelöscht, sobald meine Arbeit erledigt ist ... Warum gibt es also eine Zeit?
Ich bin die dümmste Person
Weil einige Fehler auftreten können. Schauen Sie sich den letzten Punkt an.
Krzysiek Dróżdż
Danke, großartig ... Nur eine Frage. Wie ich verstehe, my_task_function_semaphoremuss ich, wenn ich als Namen für transient verwende, alle anderen Cron mit demselben Namen verwenden?
Ich bin die dümmste Person
@IamtheMostStupidPerson es hängt davon ab, was Sie erreichen möchten ... Wenn nur eine Aufgabe in einem bestimmten Moment funktionieren soll, dann ja - alle Aufgaben sollten den gleichen vorübergehenden Namen wie das Semaphor verwenden
Krzysiek Dróżdż
1
Ich habe ähnliche Dinge mit Job Queue-Tools wie Gearman gemacht. Diese Implementierung kann helfen: github.com/10up/WP-Minions
Fayaz