+ Start a Discussion
Peter Davids 4Peter Davids 4 

Does queueing a future method count as DML?


 
Hi all,

We need to implement the following pattern at my org:
  • callout to external data source
  • if that callout takes too long (according to some configurable threshold), log an error (ie do some DML)
  • if that callout timed out on the remote server, try it again
Recognizing the potential for the dreaded "You have uncommitted work pending. Please commit or rollback before calling out." error, I put the error logging code in a future method, thus isolating the DML from the callouts. However, the error is still being thrown. I reduced the issue down to this pattern:
public static void foo() {
    Http http = new Http();
    HttpRequest req = new Httprequest();
    req.setEndpoint('https://test.salesforce.com'); //whatever endpoint
    req.setMethod('GET');
    http.send(req); //works fine
    bar();
    http.send(req); //throws calloutexception
}

@future public static void bar() {

}
Am I correct to assume that calling a future method counts as a DML operation? Is there any documentation I'm missing somewhere?

 
Best Answer chosen by Peter Davids 4
Peter Davids 4Peter Davids 4

All Answers

Aslam ChaudharyAslam Chaudhary
I hope calling future method does not count against DML operation. But future method have its own limitations 
You can find more about governing limits here
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm
 
Peter Davids 4Peter Davids 4
Looks like it doesn't count as DML for the purposes of governor limits, just for CalloutExceptions. Here's the limit usage for the above test code:
 
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 1 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 1 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
Aslam ChaudharyAslam Chaudhary
Let me know if you need Any other help in this thread.
Peter Davids 4Peter Davids 4
Yeah I'd still like to know for sure if this is the correct conclusion--it seems you can't do callouts after DML or after queueing a future method. I can't find this documented anywhere and it cost me (and possibly others) a lot of time trying to debug.
Aslam ChaudharyAslam Chaudhary
I am 100% sure you cannot do callouts after DML because I already faced this. There might be a reason behind this architecture.    

I am not sure about future method. Let me know If you want me to confirm this.
 
Peter Davids 4Peter Davids 4
Yeah, that's basically all I'm trying to figure out here. The above code snippet pretty definitively shows that you can't do callouts after queueing future methods, but I can't find that fact documented anywhere. So I can't tell if this is a bug, an undocumented feature, or if I'm just doing something wrong.
Naval Sharma4Naval Sharma4
You should do this in the following way.
First Make a callout 
Check for the timeout 
If YES - Then call Future method to log the error and re do the callout 
No - Do whatever operation you want to perform with the response
 
Future method gets executed in a different transaction (Asynchronous way) and it has it's own limits which you can see in another debug log generated ( future call ). You won't see DML operation count performed in future method in the original transaction logs.

Hope it helps.
Aslam ChaudharyAslam Chaudhary
I hope you are not doing something wrong. Please refer below links.

https://help.salesforce.com/articleView?id=000003701&type=1 

https://help.salesforce.com/articleView?id=000079772&type=1


Hope this will help.
Peter Davids 4Peter Davids 4
Naval--so you're suggesting to make the second callout in the async method? That won't work because 1. DML before callout 2. We need the data synchronously so we can pass it back to the frontend. The issue at hand is that you can't call future methods before doing a callout, the question is just why.

Aslam--appreciate the links. Definitely some workarounds to consider but I'm still curious if anyone else has encountered this issue or if SF knows about it.
Peter Davids 4Peter Davids 4
This was selected as the best answer
Naval Sharma4Naval Sharma4
No, that's not what I am saying.

See -
You will have to call your method recursively until you get the response ( I won't recommend you doing so because you may hit another governor limit ( 100 API callouts are allowed in a single transaction) and keep login the timeout error ( in future call ) .