Queueable Apex
The best features of Queueable Apex is job chaining. If you ever need to run jobs sequentially, Queueable Apex is only option.
To chain a job to another executing job, submit the second_job by using execute() method of your queueable class. You can add only one job from an executing job, which means that only one child job can exist for each parent job.
For example, if you have a second class called Second_Job that implements the Queueable interface, you can add this class to the queue in the execute() method as follows:
Queueable Syntax:
public class SomeClass implements Queueable {
public void execute(QueueableContext context) {
//awesome code here
}
}
Chaining Jobs:
public class FirstQueClass 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 Second_Job());
}
}
Note: Once again, testing has a slightly different pattern. You can’t chain queueable jobs in an Apex test, doing so results in an error.
To avoid errors, you can check if Apex is running in test context by calling Test.isRunningTest() before chaining jobs.
Scenario 1:
The following apex code takes a collection of Account records, sets the parentId for each record, and then updates the records in the database.
public class UpdateParentAccountQue 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;
}
}
Add this class as a job on the queue
//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);
Monitor progress either through the Apex Jobs page or programmatically by querying AsyncApexJob.
SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID
Test Class:
@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);
//Test.startTest() and Test.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]);
}
}
The best features of Queueable Apex is job chaining. If you ever need to run jobs sequentially, Queueable Apex is only option.
To chain a job to another executing job, submit the second_job by using execute() method of your queueable class. You can add only one job from an executing job, which means that only one child job can exist for each parent job.
For example, if you have a second class called Second_Job that implements the Queueable interface, you can add this class to the queue in the execute() method as follows:
Queueable Syntax:
public class SomeClass implements Queueable {
public void execute(QueueableContext context) {
//awesome code here
}
}
Chaining Jobs:
public class FirstQueClass 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 Second_Job());
}
}
Note: Once again, testing has a slightly different pattern. You can’t chain queueable jobs in an Apex test, doing so results in an error.
To avoid errors, you can check if Apex is running in test context by calling Test.isRunningTest() before chaining jobs.
Scenario 1:
The following apex code takes a collection of Account records, sets the parentId for each record, and then updates the records in the database.
public class UpdateParentAccountQue 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;
}
}
Add this class as a job on the queue
//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);
Monitor progress either through the Apex Jobs page or programmatically by querying AsyncApexJob.
SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID
Test Class:
@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);
//Test.startTest() and Test.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]);
}
}
No comments:
Post a Comment