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
Vidéo de démonstration Trail Together
Vous souhaitez être guidé pas à pas pendant que vous travaillez sur cette étape ? Regardez cette vidéo qui fait partie de la série Trail Together sur Trailhead Live.
(Ce clip commence à 52 min 38 s, au cas où vous voudriez revenir en arrière et regarder à nouveau le début de l’étape.)
Apex pour file d'attente
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
Queueable
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, soit sur la page Tâches Apex de l’interface utilisateur de Salesforce, soit 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
étant limitées à des types de données primitifs (ou des collections de primitifs), 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 la tâche pour surveiller sa progression, soit sur la page Tâches Apex, soit 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. Toutefois, cette limite peut être outrepassée à l’aide de la fonctionnalité de configuration de la profondeur de pile des tâches pour file d’attente chaînées.
Ressources