๐ โโ๏ธ 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: