Erfassen Sie Ihre Fortschritte
Trailhead-Startseite
Trailhead-Startseite

Steuern von Prozessen mit Queueable Apex

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, haben Sie Folgendes gelernt:
  • Zeitpunkt für die Verwendung der Queueable-Schnittstelle
  • Unterschiede zwischen Queueable- und Future-Methoden
  • Syntax von Queueable Apex
  • Queueable-Methoden – bewährte Vorgehensweisen

Queueable Apex

Das in der Version Winter '15 veröffentlichte Queueable Apex ist im Wesentlichen eine Obermenge von Future-Methoden mit ein bisschen "Geheimzutat". Wir haben die Einfachheit von Future-Methoden und die Leistungsfähigkeit von Batch-Apex genommen und diese zu Queueable Apex vermischt. Sie erhalten damit eine Klassenstruktur, die die Plattform für Sie serialisiert, sowie eine vereinfachte Schnittstelle ohne die Methoden start und finish und haben sogar die Möglichkeit, mehr als primitive Argumente zu verwenden! Zum Aufrufen wird eine einfache System.enqueueJob()-Methode verwendet, die eine Auftrags-ID zurückgibt, die Sie überwachen können. Das ist wohl die beste Erfindung, seit es Schokolade gibt!

Mit Queueable Apex können Sie Aufträge für die asynchrone Verarbeitung ähnlich wie bei Future-Methoden übermitteln, haben aber zusätzlich folgende Vorteile:
  • Nicht primitive Typen: Ihre Queueable-Klasse kann Mitgliedsvariablen mit nicht primitiven Datentypen enthalten, wie etwa sObjects oder benutzerdefinierte Apex-Typen. Auf diese Objekte kann während der Ausführung des Auftrags zugegriffen werden.
  • Überwachen: Wenn Sie Ihren Auftrag durch Aufrufen der System.enqueueJob-Methode senden, gibt die Methode die ID des AsyncApexJob-Datensatzes zurück. Anhand der ID können Sie den Auftrag identifizieren und seinen Fortschritt überwachen, entweder über die Salesforce-Benutzeroberfläche auf der Seite "Apex-Aufträge" oder programmatisch durch Abfrage Ihres Datensatzes aus AsyncApexJob.
  • Verketten von Aufträgen: Sie können zwei Aufträge miteinander verketten, indem Sie einen zweiten Auftrag aus einem laufenden Auftrag heraus starten. Das Verketten von Aufträgen ist hilfreich, wenn die Verarbeitung sequenziell durchgeführt werden muss.

Queueable im Vergleich zu Future

Da Queueable-Methoden von der Funktion her gesehen mit Future-Methoden gleichbedeutend sind, sollten Sie eher Queueable- statt Future-Methoden verwenden. Das heißt jetzt aber nicht unbedingt, dass Sie hergehen und sofort alle Ihr Future-Methoden refakturieren müssen.

Ein weiterer Grund für die Verwendung von Future- statt Queueable-Methoden liegt vor, wenn die Funktionalität manchmal synchron und manchmal asynchron ausgeführt wird. Es ist viel einfacher, eine Methode auf diese Weise zu refakturieren, als sie in eine Queueable-Klassen umzuarbeiten. Dies ist praktisch, wenn Sie feststellen, dass Teile Ihres bestehenden Codes in die asynchrone Ausführung verlagert werden müssen. Sie erstellen dann einfach eine ähnliche Future-Methode, die Ihre synchrone Methode wie folgt umschließt:

@future
static void myFutureMethod(List<String> params) {
    // call synchronous method
    mySyncMethod(params);
}

Queueable Syntax

Für die Nutzung von Queueable Apex implementieren Sie einfach die Queueable-Schnittstelle.

public class SomeClass implements Queueable { 
    public void execute(QueueableContext context) {
        // awesome code here
    }
}

Beispielcode

Ein gängiges Szenario besteht darin, dass man eine Gruppe von sObject-Datensätzen nimmt, einige Verarbeitungsschritte durchführt, wie etwa einen Callout an einen externen REST-Endpunkt oder die Durchführung von Berechnungen, und die Datenbanksätze dann asynchron in der Datenbank aktualisiert. Da @future-Methoden auf primitive Datentypen (oder Arrays bzw. Sammlungen primitiver Datentypen) beschränkt sind, ist Queueable Apex die perfekte Wahl. Der folgende Code nimmt eine Sammlung von Account-Datensätzen, legt die parentId für jeden Datensatz fest und aktualisiert die Datensätze dann in der Datenbank.

public class UpdateParentAccount implements Queueable {
    
    private List<Account> accounts;
    private ID parent;
    
    public UpdateParentAccount(List<Account> records, ID id) {
        this.accounts = records;
        this.parent = id;
    }

    public void execute(QueueableContext context) {
        for (Account account : accounts) {
          account.parentId = parent;
          // perform other processing or callout
        }
        update accounts;
    }
    
}

Führen Sie folgenden Code aus, um diese Klasse als Auftrag zur Warteschlange hinzuzufügen:

// find all accounts in ‘NY’
List<Account> accounts = [select id from account where billingstate = ‘NY’];
// find a specific parent account for all records
Id parentId = [select id from account where name = 'ACME Corp'][0].Id;

// instantiate a new instance of the Queueable class
UpdateParentAccount updateJob = new UpdateParentAccount(accounts, parentId);

// enqueue the job for processing
ID jobID = System.enqueueJob(updateJob);

Nachdem Sie Ihre Queueable-Klasse zwecks Ausführung gesendet haben, wird der Auftrag zur Warteschlange hinzugefügt und verarbeitet, sobald Systemressourcen verfügbar sind.

Anhand der neuen Auftrags-ID können Sie den Fortschritt überwachen, und zwar entweder über die Seite "Apex-Aufträge" oder programmatisch durch Abfragen von AsyncApexJob:

SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID

Testen von Queueable Apex

Der folgende Beispielcode zeigt, wie Sie die Ausführung eines Queueable-Auftrags in einer Testmethode prüfen. Der Code ähnelt dem zum Testen von Batch-Apex stark. Um sicherzustellen, dass dieser Queueable-Prozess innerhalb der Testmethode ausgeführt wird, wird der Auftrag zwischen dem Test.startTest- und dem Test.stopTest-Block in die Warteschlange eingereiht. Das System führt alle asynchronen Prozesse, die in einer Testmethode gestartet wurden, nach der Test.stopTest-Anweisung synchron aus. Als Nächstes prüft die Testmethode die Ergebnisse des Queueable-Auftrags, indem sie die vom Auftrag aktualisierten Datensätze abfragt.

@isTest
public class UpdateParentAccountTest {

    @testSetup 
    static void setup() {
        List<Account> accounts = new List<Account>();
        // add a parent account
        accounts.add(new Account(name='Parent'));
        // add 100 child accounts
        for (Integer i = 0; i < 100; i++) {
            accounts.add(new Account(
                name='Test Account'+i
            ));
        }
        insert accounts;
    }
    
    static testmethod void testQueueable() {
        // query for test data to pass to queueable class
        Id parentId = [select id from account where name = 'Parent'][0].Id;
        List<Account> accounts = [select id, name from account where name like 'Test Account%'];
        // Create our Queueable instance
        UpdateParentAccount updater = new UpdateParentAccount(accounts, parentId);
        // startTest/stopTest block to force async processes to run
        Test.startTest();        
        System.enqueueJob(updater);
        Test.stopTest();        
        // Validate the job ran. Check if record have correct parentId now
        System.assertEquals(100, [select count() from account where parentId = :parentId]);
    }
    
}

Verketten von Aufträgen

Eines der besten Features von Queueable Apex ist das Verketten von Aufträgen. Falls Sie jemals Aufträge sequenziell ausführen müssen, könnte Ihnen Queueable Apex das Leben deutlich leichter machen. Um zwei Aufträge miteinander zu verketten, senden Sie den zweiten Auftrag über die execute()-Methode Ihrer Queueable-Klasse. Sie können nur einen Auftrag aus einem laufenden Auftrag hinzufügen, das heißt, es darf zu jedem übergeordneten Auftrag nur einen untergeordneten Auftrag geben. Wenn Sie zum Beispiel über eine zweite Klasse mit dem Namen SecondJob verfügen, die die Queueable-Schnittstelle implementiert, können Sie diese Klasse über die execute()-Methode wie folgt zur Warteschlange hinzufügen:

public class FirstJob implements Queueable { 
    public void execute(QueueableContext context) { 
        // Awesome processing logic here    
        // Chain this job to next job by submitting the next job
        System.enqueueJob(new SecondJob());
    }
}

Auch hier ist ein etwas anderes Testmuster notwendig. Die Verkettung von Queueable-Aufträgen in einem Apex-Test ist nicht möglich und führt zu einem Fehler. Um solche Fehler zu vermeiden, sollten Sie überprüfen, ob Apex im Testkontext ausgeführt wird, indem Sie vor der Verkettung von Aufträgen Test.isRunningTest() aufrufen.

Wichtige Punkte

Queueable Apex ist ein hervorragendes neues Tools, bei dem jedoch ein paar Punkte zu beachten sind:
  • Die Ausführung eines in der Warteschlange befindlichen Auftrags erfolgt unter Anwendung der gemeinsamen Obergrenze für die asynchrone Ausführung von Apex-Methoden.
  • Pro Transaktion können Sie mit System.enqueueJob bis zu 50 Aufträge zur Warteschlange hinzufügen.
  • Beim Verketten von Aufträgen können Sie mit System.enqueueJob nur einen Auftrag aus einem laufenden Auftrag hinzufügen, das heißt, es darf zu jedem übergeordneten Queueable-Auftrag nur einen untergeordneten Auftrag geben. Das Starten mehrerer untergeordneter Aufträge vom gleichen Queueable-Auftrag ist ein Tabu.
  • Die Verkettungstiefe ist nicht beschränkt, das heißt, dass Sie zwei Aufträge verketten können und diesen Prozess mit jedem neuen untergeordneten Auftrag fortsetzen können, um diese mit einem neuen untergeordneten Auftrag zu verknüpfen. Bei Developer Edition- und Testorganisationen ist die maximale Stapeltiefe für verkettete Aufträge fünf, d. h., ein Auftrag kann nur jeweils vier Mal verkettet werden und es dürfen sich maximal fünf Aufträge in der Kette befinden (der anfänglich übergeordnete Queueable-Auftrag eingeschlossen).

Ressourcen

Hinweis

Hinweis

Nicht vergessen: Dieses Modul bezieht sich auf Salesforce Classic. Wenn Sie Ihre Übungs-Organisation starten, wechseln Sie zu Salesforce Classic, um diese Aufgabe abzuschließen.