Suivez votre progression
Accueil Trailhead
Accueil Trailhead

Contrôle des processus avec Apex pour file d'attente

Objectifs de formation

Dans cette unité, vous allez découvrir :
  • Quand utiliser l’interface Queueable
  • Les différences entre les méthodes pour file d’attente et futures
  • La syntaxe d’un Apex pour file d’attente
  • Les meilleures pratiques d’utilisation de méthodes pour file d’attente

Queueable Apex

Publiée dans Winter '15, la méthode Apex pour file d'attente est essentiellement une super-série des méthodes futures avec un #ingrédient supplémentaire. Nous nous sommes appuyés sur la simplicité des méthodes futures et la puissance de la méthode Apex par lot pour former la méthode Apex pour file d'attente ! Elle offre une structure de classe que la plate-forme sérialise pour vous, une interface simplifiée sans méthode start et finish, et permet même d’utiliser davantage que de simples arguments primitifs ! Elle est appelée par une simple méthode System.enqueueJob(), qui renvoie un ID de tâche que vous pouvez surveiller. Mieux que le fil à couper le beurre !

Un Apex pour file d’attente permet de soumettre des tâches pour un traitement asynchrone semblable à celui des méthodes futures avec des avantages supplémentaires :
  • Types non primitifs : votre classe pour file d’attente peut contenir des variables membres de types de données non primitifs, tels que des sObjects ou des types Apex personnalisés. Ces objets peuvent être accédés lors de l’exécution de la tâche.
  • Surveillance : lorsque vous soumettez votre tâche en invoquant la méthode System.enqueueJob, la méthode renvoie l’ID de l’enregistrement AsyncApexJob. Vous pouvez utiliser cet ID pour identifier votre tâche et surveiller sa progression, via la page Tâches Apex de l’interface utilisateur de Salesforce, ou par programmation en interrogeant votre enregistrement dans AsyncApexJob.
  • Chaînage des tâches : vous pouvez chaîner une tâche à une autre en commençant la deuxième tâche à partir d’une tâche en cours d’exécution. Le chaînage des tâches est utile pour un traitement séquentiel.

Méthodes futures et pour file d’attente

Le fonctionnement des méthodes pour file d’attente est semblable à celui des méthodes futures. Par conséquent, vous allez souvent préférer utiliser des méthodes pour file d’attente plutôt que des méthodes futures. Cela ne signifie pas pour autant que vous devez refactoriser maintenant toutes vos méthodes futures.

Vous pouvez également utiliser des méthodes futures à la place de méthodes pour file d’attente lorsque l’exécution de votre fonctionnalité est parfois synchrone et parfois asynchrone. Il est plus facile de refactoriser une méthode de cette façon que de la convertir en classe pour file d’attente. C’est pratique lorsque vous découvrez qu’une partie de votre code existant doit basculer vers une exécution asynchrone. Il suffit de créer une méthode future similaire qui incorpore votre méthode synchrone comme suit :

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

Syntaxe d’une méthode pour file d'attente

Pour utiliser un code Apex pour file d’attente, il suffit d’implémenter l’interface Queueable.

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

Exemple de code

Un scénario courant consiste à sélectionner une série d’enregistrements sObject, d’exécuter un traitement, par exemple un appel externe à un point de terminaison REST externe ou des calculs, puis de mettre les enregistrements à jour de façon asynchrone dans la base de données. Les méthodes @future sont limitées à des types de données primitifs (groupes ou collections de primitifs). Par conséquent, un code Apex pour file d’attente est le choix idéal. Le code ci-dessous utilise une série d’enregistrements Compte, définit le parentId de chaque enregistrement, puis met à jour les enregistrements dans la base de données.

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

Pour ajouter cette classe à une tâche dans la file d’attente, exécutez le code suivant :

// 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);

Une fois votre classe pour file d’attente soumise pour exécution, la tâche est ajoutée à la file d’attente et traitée dès que les ressources système sont disponibles.

Vous pouvez utiliser le nouvel ID de tâche pour surveiller la progression, via la page Tâches Apex ou par programmation en interrogeant AsyncApexJob :

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

Test d’un Apex pour file d'attente

L’exemple de code ci-dessous montre comment tester l’exécution d’une tâche pour file d’attente dans une méthode de test. Il est très similaire à un test de code Apex par lot. Pour s’assurer que le processus pour file d’attente est exécuté dans la méthode de test, la tâche est soumise à la file d’attente entre le bloc Test.startTest et Test.stopTest. Le système exécute tous les processus asynchrones démarrés de façon synchrone dans une méthode de test après l’instruction Test.stopTest. La méthode de test vérifie ensuite les résultats de la tâche pour file d’attente en interrogeant les enregistrements de compte mis à jour par la tâche.

@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]);
    }
    
}

Chaînage des tâches

L’une des fonctionnalités les plus intéressantes d’un code Apex pour file d’attente est le chaînage des tâches. Si vous devez exécuter des tâches de façon séquentielle, un code Apex pour file d’attente peut considérablement simplifier votre travail. Pour chaîner une tâche à une autre tâche, soumettez la deuxième tâche à partir de la méthode execute() de votre classe pour file d’attente. Vous pouvez ajouter une seule tâche à partir d’une tâche en cours d’exécution, ce qui signifie qu’une seule tâche enfant peut exister pour chaque tâche parente. Par exemple, si vous avez une deuxième classe appelée SecondJob qui implémente l’interface Queueable, vous pouvez ajouter cette classe à la file d’attente dans la méthode execute() comme suit :

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

Une nouvelle fois, le modèle du test est légèrement différent. Vous ne pouvez pas chaîner des tâches pour file d’attente dans un test Apex, ce qui génère une erreur. Pour éviter toute erreur indésirable, vous pouvez vérifier si le code Apex est exécuté dans un contexte de test en appelant Test.isRunningTest() avant de chaîner les tâches.

À retenir

Apex pour file d’attente est un nouvel outil très utile, mais vous devez tenir compte des points suivants :
  • L’exécution d’une tâche pour file d’attente est prise en compte dans la limitation partagée d’exécution de méthodes Apex asynchrones.
  • Vous pouvez ajouter jusqu’à 50 tâches à la file d’attente avec System.enqueueJob dans une seule transaction.
  • Lors du chaînage de tâches, vous pouvez ajouter une seule tâche à partir d’une tâche en cours d’exécution avec System.enqueueJob, ce qui signifie qu’une seule tâche enfant peut exister pour chaque tâche pour file d’attente parente. Vous ne pouvez pas démarrer plusieurs tâches enfants à partir de la même tâche pour file d’attente.
  • La profondeur du chaînage des tâches est illimitée, ce qui signifie que vous pouvez chaîner une tâche à une autre et répéter ce processus en chaînant chaque tâche enfant successive à une nouvelle tâche enfant. Cependant, pour des organisations Developer Edition et d’évaluation, la profondeur maximale de la pile est de 5 pour les tâches chaînées. Cela signifie que vous pouvez chaîner des tâches quatre fois et que le nombre maximal de tâches dans la chaîne est de 5, qui comprend la tâche pour file d’attente parente initiale.

Ressources

Remarque

Remarque

N’oubliez pas que ce module est conçu pour Salesforce Classic. Lorsque vous lancez votre organisation d’exercice, basculez vers Salesforce Classic pour relever ce défi.