Salesforce Tips & Tricks Blog

Asynchronous Apex - Avoiding @Future Governor Limits

Posted in Back2Basics by Milan
Share:

๐Ÿ™…โ€โ™‚๏ธ We at www.cloudbus.digital, just like every other Salesforce developer, are intimately familiar with Governor Limits. Love them or hate them, they all have a good reason to exist. They prevent us from going too crazy with extreme algorithms and stop us from abusing the resources given to us by Salesforce itself.

๐Ÿ’ก There are times when we come across a rare situation, where a Governor Limit blocks something that we need our logic to do. One such scenario involves 3rd party packages, especially ones that do complex Apex Trigger logic, and use asynchronous processing. Letโ€™s just for a second imagine that we know exactly what is happening under the hood of the managed package, and take a look at the following scenario:

๐’๐œ๐ž๐ง๐š๐ซ๐ข๐จ:

Installed managed package performs complex calculations on a custom object Quote__c and populates a field Price__c. Due to the complexity of the calculations, the package does this in an asynchronous context, using specifically the @Future annotation.

Our own custom logic performs subsequent calculations that react to the changes on the Quote__c.Price__c field. This custom logic calculates the impact of a price change, and is also very complex. So naturally, we try to use the @Future annotation as well, and apply it to our ServiceClass.calculateImpact()

๐๐ซ๐จ๐›๐ฅ๐ž๐ฆ:

If youโ€™ve been paying attention, you know where this is going. An AsyncException is thrown, because Salesforce Governor Limits donโ€™t allow calling @Future in an already @Future asynchronous context.

โ€œSystem.AsyncException: Future method cannot be called from a future or batch methodโ€

๐’๐จ๐ฅ๐ฎ๐ญ๐ข๐จ๐ง:

While Governor Limits prevent using Future and Batch contexts in this way, they donโ€™t limit the Queueable asynchronous context. One possible reason is that Queueable is the asynchronous tool that gives developers the most control over the behavior of custom logic.

At this point, to solve the problem we can simply remove the @Future annotation and call our calculateImpact() method from an instance of a Queueable wrapper class. See the snippet below:

enter image description here