Action Scheduler: Wie du eine Job-Queue für WordPress verwenden kannst

Was ist ein Action Scheduler?

Der Action Scheduler ist ein kostenloses Plugin von Automattic, den Entwicklern von WooCommerce, Akismet Spam Protection und vielem mehr!

Du kannst aufwändige, unkritische Prozesse oder Aktionen damit in eine Job-Queue, sprich Warteschlange packen, die dann im Hintergrund abgearbeitet wird.

Ein Intervall für die Abarbeitung wird immer durch den Aufruf deiner Seite ausgelöst, oder im Falle von deaktivierten WordPress Cronjobs, durch das Intervall deiner echten Cronpings.

Anwendungsbeispiel

Fall: Du betreibst eine WordPress-Seite mit Mitgliedern und möchtest allen Abonnenten eine E-Mail schicken, wenn du ein neuer Blogbeitrag veröffentlicht wird.

Bei wenigen Abonnenten ist es kein Problem die E-Mails an alle zu schicken, solltest du aber mehrere Tausende Abonnenten haben, dann kann es passieren, das deine Seite einen Timeout erzeugt, da der Server überlastet ist.

Wir übergeben die Aktion also in den Action Scheduler in Paketen zu jeweils 10 Abonnenten. Im Hintergrund arbeitet der Action Scheduler dann das Versenden der E-Mails ab.

Wie du den Action Scheduler in dein WordPress Theme integrieren kannst

Um den Action Scheduler zu verwenden, musst du ihn zuerst in dein WordPress-Theme integrieren.

Dazu gibt es zwei Möglichkeiten:

  1. Installiere das WordPress-Plugin
    https://wordpress.org/plugins/action-scheduler/
  2. Integriere und lade den Plugin Code in dein Theme
    https://github.com/woocommerce/action-scheduler/

In diesem Tutorial werden wir den Action Scheduler manuell in das Theme integrieren. Gehe dabei wie folgt vor:

1. Kopiere den kompletten Ordner von Github in dein Child-Theme

/theme-child/vendor/action-scheduler

2. Lade den Action Scheduler in deiner functions.php

$file = dirname( __FILE__ ) . '/vendor/action-scheduler/action-scheduler.php' );
if ( file_exists( $file ) {
    include_once $file;
}Code-Sprache: PHP (php)

Wenn du alles richtig gemacht hast, hat das Plugin nun 4 neue Tabellen erstellt:

  • wp_actionscheduler_actions
  • wp_actionscheduler_claims
  • wp_actionscheduler_groups
  • wp_actionscheduler_logs

Besonders wichtig ist die erste Tabelle: wp_actionscheduler_actions. Hier werden die Aufträge angelegt.

Die interessanten Spalten sind hier:

  • hook = Die Action, die ausgeführt wird.
  • status = Der Status des Jobs (pending, in-progress, complete, failed, canceled).
  • args = Die Argumente, die der Action übergeben werden. In unserem Beispiel die post_id und 10 user_ids

Wie du eine Aktion zur asynchronen Ausführung planen kannst

as_enqueue_async_action( 'sende_mail_an_abonnenten', array( $post_id, $user_ids ) );Code-Sprache: PHP (php)

Mit dem Hook as_enqueue_async_action('action_name', 'argumente') erstellst du einen Hintergrundjob, der einmalig und so früh wie möglich läuft.

Zusatzinformationen

Neben diesem Hook gibt es noch weitere Optionen:

  • as_schedule_single_action() = Plant einen Hintergrundjob, der einmalig zu einem bestimmten Zeitpunkt laufen soll.
  • as_schedule_recurring_action() = Plant einen Hintergrundjob, der sich in einem vorgegbenen Interval wiederholt.

Außerdem kannst du auch geplante Jobs abbrechen oder löschen. Möchtest du mehr darüber erfahren, kannst du hier nachlesen, welche Funktionen es gibt.

Code für unser Anwendungsbeispiel

Wir planen eine Action: sende_mail_an_abonnenten für jeweils 10 Benutzer.

Die Action: sende_mail_an_abonnenten versendet dann die E-Mails in der du mit der übergebenen $post_id und den 10 $user_ids den E-Mail-Inhalt und Empfängeradressen generieren kannst.

add_action( 'transition_post_status', 'benachrichtige_abonnenten', 10, 3 );

function benachrichtige_abonnenten( $new_status, $old_status, $post ) {

    // überprüfe ob der Post vorher noch nicht veröffentlicht war und ein Standard Post ist.
    if( 'publish' === $new_status && 'publish' !== $old_status && 'post' === $post->post_type ) {
        
        // nur Benutzer mit der Abonnenten Rolle
        $only_subscribers = array(
            'role__in' => 'subscriber'
        );

        $subscribers = get_users( $only_subscribers );
        
        // unser leeres User IDs Array. Wird nach 10 Benutzern zurückgesetzt.
        $user_ids = array();

        // Hier loopen wir durch alle gefundenen Benutzer und erstellen Action Scheduler Jobs für jeweils 10 User IDs.
        foreach ( $subscribers as $subscriber ) {

            // Wenn wir bereits 10 User IDs haben erstellen wir einen Action Scheduler Job und leeren das User ID Array.
            if ( 10 <= count( $user_ids ) ) {

                // Den Action Scheduler Job planen und Post ID und 10 User IDs übergeben.
                as_enqueue_async_action( 'sende_mail_an_abonnenten', array( $post->ID, $user_ids ) );
                // Das User IDs Array zurücksetzen.
                $user_ids = array();

            }

            // die Benutzer ID dem User ID Array hinzufügen.
            $user_ids[] = $subscriber->ID;
        }

    }

}Code-Sprache: PHP (php)

Aufräumen der Datenbanktabelle

Leider räumt sich die Tabelle wp_actionscheduler_actions nicht so schön von selbst auf. Bei vielen gelaufenen Jobs sammeln sich hier schnell viele abgeschlossene Jobs. Das war sogar ein Problem mit WooCommerce selbst, wo dann bei 900 Artikeln schnell mehrere Millionen Datenbankeinträge gesammelt waren.

Um diese Tabelle zu bereinigen, können wir einen Cronjob anlegen, der alle Einträge mit dem Status: complete, failed, canceled bereinigt.

add_action( 'cleanup_actionscheduler', 'bereinige_den_actionscheduler' );

function bereinige_den_actionscheduler() {

    global $wpdb;
    $table_name = $wpdb->prefix . 'actionscheduler_actions';

    $states = array(
        'complete',
        'failed',
        'canceled'
    );

    foreach ( $states as $status ) {

        $wpdb->delete( $table_name, array( 'status' => $status ), array( '%s' ) );

    }
    
}Code-Sprache: PHP (php)