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
La méthode Apex pour file d’attente est essentiellement une super-série des méthodes futures avec les avantages supplémentaires suivants :
- Types non primitifs : votre classe
Queueablepeut 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 d’Apex 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 workflow Apex pour file d’attente courant consiste à obtenir un ensemble d’enregistrements sObject, à les traiter, puis à les mettre à jour dans la base de données de manière asynchrone. Les méthodes futures é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 de 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.
La méthode setup() est annotée avec @testSetup. Cette annotation vous permet de créer des enregistrements de test courants disponibles pour toutes les méthodes de la classe. Toutes les mises à jour des enregistrements de test sont annulées une fois l’exécution de chaque méthode de test terminée. Bien que cette classe de test n’inclue qu’une seule méthode (en plus de la méthode setup() elle-même), nous avons inclus l’annotation @testSetup ici à titre d’exemple. Dans ce cas, la méthode setup() crée un enregistrement de compte parent et 100 enregistrements de compte enfant. Ensuite, elle insère les enregistrements dans la base de données. Ces données sont utilisées par la classe pour file d’attente.
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;
}
@isTest
static 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());
}
}Vous pouvez utiliser des profondeurs de pile définies pour tester des chaînes de tâches pour file d’attente, mais tenez compte des limitations des gouverneurs Apex applicables. Consultez la section Ajout d’une tâche pour file d’attente avec une profondeur de pile spécifiée.
À retenir
Apex pour file d’attente est un 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.enqueueJobdans 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 avec chaque 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
