img1

Preface

Checkout the following articles before tackling this one:

  1. Basics and Definitions
  2. Future Methods
  3. Batch Apex

Learning Objectives

After completing this article, you’ll be able to describe:

Prologue

Queueable apex is an apex method use to run batch processes asynchronously. Queueable apex is the abstract combination between future methods and batchable apex. Executing Queueable apex enqueues each job to the Apex job queue. This feature is a evolution over Future methods, they functionally equivalent, however Queueable apex allows job chaining and usage for more complex data types. They also share a benefit of having some higher governor limits.

Benefits

Listed are some the advantages when using Queueable apex:

  • Chaining jobs: Submitted jobs can be chained together, by starting a second job from a running job
  • You can monitor submitted jobs progress by querying on the job-id returned
  • Provides the capability to use non-primitive data types, such as sObjects or custom Apex types

Limitations

Please bare the following in mind, when considering Queueable apex implementations:

  • The execution for Queueable apex counts against shared asynchronous method call limit
  • You can only add up to 50 jobs to the queue with System.enqueueJob
  • When chaining jobs, you can only can add one job from the current job executing
    • meaning that only one child job can exist for each parent Queueable job

Best Practices

Listed below are a few best practices to keep into consideration for Queueable apex:

  1. Do not enqueue a job in a trigger, if you can’t guarantee that , such invocation will cause further executions
  2. Queueable apex only has the execute method, you are not given the luxury of the start method in batchable apex
    1. Therefore you of to build helper methods to query records and set member variables for processing
  3. Only chain one job per executing job transaction context

Queueable Apex Syntax

To use Queueable Apex, simply implement the Queueable interface.

1
2
3
4
5
6
public with sharing class QueueableClass imeplements Queueable {
    List<Sobject> records;
    public void execute(QueueableContext qc){
            // perform processing on this.records
    }
}

Monitoring

The result of the method System.enqueueJob will return the current queue transaction id. You can use that id to query the AsyncApexJob records. Each Queueable Apex invocation creates an AsyncApexJob record.

Practical Example

The example below demonstrates using the Queuable apex feature to update a custom boolean field(Aligned__c) on the Account object, to equal true only if some the associated opportunities Amount is > $5000.

  1. Create a Boolean field on the Account object called Aligned.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public with sharing QueueAccounts implements Queueable {
    Set<ID> records;
    public QueueAccounts(Set<ID> ids){
        this.ids = ids;
    }
    public void execute(QueueableContext qc){
        List<Account> accounts = new List<Account>();
        for(Account record: [SELECT Id,(SELECT Id FROM Opportunities WHERE Amount > 5000) 
                             FROM Account WHERE id IN this.ids]){
            record.Aligned__c = true;
            accounts.add(record);
        }
        if(!accounts.isEmpty()){
            update accounts;
        }
    }
}

Testing QueueAccounts

The following code snippet below tests the QueueAccounts class.

Note: this example uses the @testSetup annotation. Methods defined with the @testSetup annotation are used for creating common test records that are available for all test methods in the class. You must run the Queueable instantiation synchronously using Test.startTest() and Test.stopTest().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@isTest
public class QueueAccountsTest {

    @testSetup
    public static void setup(){
        Account accountRecord = new Account(Name='Test Queueable');
        Opportunity opportunityRecord = new Opportunity();
        opportunityRecord.CloseDate = Date.Today().addMonths(2);
        opportunityRecord.Name = 'Awesome Opportunity';
        opportunityRecord.Amount = 5670;

        insert accountRecord;
        opportunityRecord.AccountId = accountRecord.Id;
        insert opportunityRecord;
    }
    @isTest
    public static void testAccounts(){
        Test.startTest();
        Map<Id, Account> mappedAccounts = new Map<Id, Account>([SELECT Id FROM Account WHERE Name='Test Queueable']);
        QueueAccounts queue = new QueueAccounts(mappedAccounts.keySet());
        Id jobId = System.enqueueJob(queue);
        Test.stopTest();
        Account record = [SELECT ID FROM Account WHERE Name = 'Test Queueable'];
        System.assert(record != null);
        System.assert(record.Aligned__c == true);
    }
}

Chaining Jobs

Queueable apex provides the capability to chain jobs sequentially, To chain a job to another job, submit the second job from the 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.

You can’t chain queueable jobs in an Apex test, doing so results in an error. To avoid nasty errors, you can check if Apex is running in test context by calling Test.isRunningTest before chaining jobs.

1
2
3
4
5
6
public class FirstJob implements Queueable { 
    public void execute(QueueableContext context) {    
        // Chain this job to next job by submitting the next job
        System.enqueueJob(new SecondJob());
    }
}

Epilogue

In concluding this article, Queuable apex was discussed, including but not limited to, the use cases, the various distinctions between other asynchronous features on the Salesforce platform. The best practices and limitations were also listed and described. Sample code examples were also provided to cement the concepts discussed, as well as chaining jobs. Thanks for stopping by 😃 and i hope you was able to learn something new or reinforce what you already knew. A través del aprendizaje continuo, ¡mejorará!