Future Methods Flashcards
What are Future Methods ?
- A future method runs in the background, asynchronously. You can call a future method for executing long-running operations, such as callouts to external web services or any operation you’d like to run in its own thread, on its own time.
- You can also use future methods to isolate DML operations on different sObject types to prevent the mixed DML error.
When do future method execute?
- Each future method is queued and executes when system resources become available.
- That way, the execution of your code doesn’t have to wait for the completion of a long-running operation.
- A benefit of using future methods is that some governor methods are higher, such as SOQL query limits and heap size limits.
How to define a future method ?
To define a future method, simply annotate it with the future
annotation, as follows:
global class FutureClass { @future public static void myFutureMethod() { // Perform some operations } }
What are the requirements for defining a future method ?
- Methods with the
future
annotation must be static methods, and can only return a void type. - The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.
- Methods with the
future
annotation can’t take sObjects or objects as arguments.
What is the reason why sObjects can’t be passed as arguments to future methods ?
- The reason why sObjects can’t be passed as arguments to future methods is because the sObject can change between the time you call the method and the time it executes.
- In this case, the future method gets the old sObject values and can overwrite them.
How to work with sObjects in future methods if sObjects can’t be passed as arguments to future methods?
To work with sObjects that already exist in the database, pass the sObject ID instead (or collection of IDs) and use the ID to perform a query for the most up-to-date record.
global class FutureMethodRecordProcessing { @future public static void processRecords(List<ID> recordIds) { // Get those records based on the IDs List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds]; // Process records } }
How to invoke callouts in future methods ?
The @future
annotation takes an extra parameter (callout=true)
to indicate that callouts are allowed.
global class FutureMethodExample { @future(callout=true) public static void getStockQuotes(String acctName) { // Perform a callout to an external service } }
What are the limitations that future methods have ?
Methods with the future
annotation have the following limits:
- No more than 0 in batch and future contexts; 50 in queueable context method calls per Apex invocation. Asynchronous calls, such as
@future
orexecuteBatch
called in astartTest
,stopTest
block, don’t count against your limits for the number of queued jobs. - 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 limit is for your entire org and is shared with all Asynchronous Apex: Batch Apex, Queueable apex, scheduled Apex and future methods.
How are the future jobs queued in a transaction ?
- Future jobs queued by a transaction aren’t processed if the transaction rolls back.
- Future method jobs queued before a Salesforce service maintenance downtime remains in the queue. After service downtime ends and when system resources become available, the queued future method jobs are executed. If a future method was running when downtime occurred, the future method execution is rolled back and restarted after the service comes back up.
How to test future methods ?
- To test methods defined with the
future
annotation, call the class containing the method in astartTest()
,stopTest()
code block. - All asynchronous calls made after the
startTest
method are collected by the system. WhenstopTest
is executed, all asynchronous process are run synchronously.
@isTest private class MixedDMLFutureTest { @isTest static void test1() { User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()]; // System.runAs() allows mixed DML operations in test context System.runAs(thisUser) { // startTest/stopTest block to run future method synchronously Test.startTest(); MixedDMLFuture.useFutureMethod(); Test.stopTest(); } // The future method will run after Test.stopTest(); // Verify account is inserted Account[] accts = [SELECT Id from Account WHERE Name='Acme']; System.assertEquals(1, accts.size()); // Verify user is inserted User[] users = [SELECT Id from User where username='mruiz@awcomputing.com']; System.assertEquals(1, users.size()); } }
What are the best practices to improve future method performance ?
Salesforce uses a queue-based framework to handle asynchronous processes from such sources as future methods and batch Apex.
- Avoid adding large numbers of future methods to the asynchronous queue, if possible. If more than 2000 unprocessed requests from a single organization are in the queue, any additional requests from the same organization will be delayed while the queue handles requests from other organizations.
- Ensure that future methods execute as fast as possible. To ensure fast execution of batch jobs, minimize Web service callout times and tune queries used in your future methods. The longer the future method executes, the more likely other queued requests are delayed when there are large number of requests in the queue.
- Test your future methods at scale. To help determine if delays can occur, test using an environment that generates the maximum number of future methods you’d expect to handle.
- Consider using batch Apex instead of future methods to process large number of records.