Salesforce: A Practical Approach to Queueables
Update, June 2020: Like to live dangerously? Go straight to the code. I've set up a project with the framework and some examples.
Salesforce triggers are great, but they run synchronously by default. What if you want to speed up the user experience and run noncritical tasks in the background? That’s what Queueable is for. But it’s not as simple as it’s made out to be.
I think most organizations have a simple process where they have a Trigger that calls a Trigger Handler. With a Queueable, you might think you can do something like this.
Then a Queueable to implement your business logic.
The problem with this approach is, as Brian Fear (aka sfdcfox) said in his outstanding response to my StackExchange Question: “The rule is that if you’re synchronous, you get 50 jobs for that transaction. Once you go asynchronous, you get only one child allowed.”
Brian went on to provide an example, which works great. Basically it detects if you’ve “Gone Synchronous” and runs the Queueable appropriately.
This Works Great.. But
The issue you’ll soon run into is that you can’t chain Queueables in test classes. This is maddening, really. They give you this cool way to do asynchronous processing, but cut you off at the knees in mandatory test code.
The workaround is to detect if you are working in test, and run the Queueable synchronously instead.
The only issue with this is that synchronous processing gets lower limits than asynchronous/queueable, which I found out when my bulk test code ran afoul of a CPU time limit. So in this case I created a public static Boolean variable in my Trigger Handler that I can set explicitly from the test class, that forces the test to run as a Queueable, above as isBulkTest. You just need to be careful that downstream chaining doesn’t do the same thing from the same test method.
Please let me know if this is helpful or if you have any questions. You can reach me at @BobHatcher on your friendly Twitter machine.