Thursday, February 12, 2015

Queueable vs. @future throwdown!

At first blush, the new Queueable interface appears to supersede the old @future annotation in Apex, especially now that in Spring '15 you can chain a job to another job an unlimited number of times. Yes, that's right: unlimited.

So, what's the purpose of @future in this new age of Apex?

Let's start by comparing the well known @future limits with Queuable.

@future consideration vs. Queueable
Some governor limits are higher, such as SOQL query limits and heap size limits Some governor limits are higher than for synchronous Apex, such as heap size limits
Methods with the future annotation must be static methods Queueable implementations must be instantiated as objects before the the execute() instance method is called, leaving room for additional job context
Methods with the future annotation can only return a void type Queueable classes must implement public void execute(QueueableContext), which is how a job is initiated
The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types. Methods with the future annotation cannot take sObjects or objects as arguments. A Queueable object can be constructed with any type of parameter, stored as private member variables
Can make a callout to an external service
A future method can’t invoke another future method You can chain queueable jobs. You can add only one job from an executing job, which means that only one child job can exist for each parent job.
No more than 50 method calls per Apex invocation You can add up to 50 jobs to the queue with System.enqueueJob in a single transaction
The maximum number of future method invocations per a 24-hour period is 250,000 or the number of user licenses in your organization multiplied by 200, whichever is greater. This is an organization-wide limit and is shared with all asynchronous Apex: Batch Apex, Queueable Apex, scheduled Apex, and future methods. The licenses that count toward this limit are full Salesforce user licenses or Force.com App Subscription user licenses.

From the reverse side, what about known limits with Queuable?

Queueable consideration vs. @future
The execution of a queued job counts once against the shared limit for asynchronous Apex method executions.
You can add up to 50 jobs to the queue with System.enqueueJob in a single transaction. No more than 50 method calls per Apex invocation
No limit (except in DE and Trialforce orgs) is enforced on the depth of chained jobs, which means that you can chain one job to another job and repeat this process with each new child job to link it to a new child job. n/a (cannot chain @future methods)
When chaining jobs, you can add only one job from an executing job with System.enqueueJob, which means that only one child job can exist for each parent queueable job. Starting multiple child jobs from the same queueable job isn’t supported.
You can’t chain queueable jobs in an Apex test. Doing so results in an error. To avoid getting an error, you can check if Apex is running in test context by calling Test.isRunningTest() before chaining jobs.

The verdict: Implement Queueable as a standard approach, and only look to @future if for some reason Queueable gives you unexpected or undocumented problems.