Tuesday, November 20, 2018

Asynchronous Apex: Queueable Apex in Salesforce.com

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

    }

}











No comments:

Post a Comment

Validation in flow input text field in sfdc: Maximum 255 characters limit

The input text field validate in sfdc flow behaves opposite of the generic sfdc validation rule.  Here the validation formula is evaluating ...