I need to refactor the code to avoid getting the error System.LimitException: Too many future calls: 51
and also need to overcome the error System.LimitException: Too many callouts: 101
I am bulk uploading leads and all leads must make an individual rest api callout. I am inserting more than 100 lead records via Data Import Wizard.
I thought of writing the trigger like by sending the leads in the trigger as a list. This will solve the too many future call error but will not solve the too many call out error:
if(Trigger.isAfter && trigger.isInsert){ if(Trigger.new != null){ List leadIds = new List(); for(lead ld:trigger.new){ if(ld.Messaging_Source__c == null){ leadIds.add(ld.Id); } } if (leadIds != null) YMTemplateCallout.sendYMTemplateCalloutREST(leadIds); } }
So decided to use queueable apex for which I have the following trigger:
if(Trigger.isAfter && trigger.isInsert){ if(Trigger.new != null){ system.enqueueJob(new YMTemplateCallout(Trigger.new)); } }
How to write a queueable apex class for this?
Came across this post: Queuable apex basics - Salesforce Stack Exchange
Also check out: Control Processes with Queueable Apex Unit | Salesforce Trailhead
Ended up with the following code and is working fine:
public class YMTemplateCallout implements Queueable { private List leadListToCallout; YM_Msg_Template_Notify__c data1 = YM_Msg_Template_Notify__c.getvalues('templatecallout1'); //---Whatsapp_Opt_in__c == false YM_Msg_Template_Notify__c data2 = YM_Msg_Template_Notify__c.getvalues('templatecallout2'); //---Whatsapp_Opt_in__c == true msgtemplateWrapper template = new msgtemplateWrapper(); msgtemplateWrapper.body TempBody = new msgtemplateWrapper.body(); msgtemplateWrapper.language lang = new msgtemplateWrapper.language(); msgtemplateWrapper.template temp = new msgtemplateWrapper.template(); // Constructor public YMTemplateCallout(List leadsFromTrigger){ this.leadListToCallout = leadsFromTrigger; YM_Msg_Template_Notify__c data1 = YM_Msg_Template_Notify__c.getvalues('templatecallout1'); //---Whatsapp_Opt_in__c == false YM_Msg_Template_Notify__c data2 = YM_Msg_Template_Notify__c.getvalues('templatecallout2'); //---Whatsapp_Opt_in__c == true msgtemplateWrapper template = new msgtemplateWrapper(); msgtemplateWrapper.body TempBody = new msgtemplateWrapper.body(); msgtemplateWrapper.language lang = new msgtemplateWrapper.language(); msgtemplateWrapper.template temp = new msgtemplateWrapper.template(); } public void execute(QueueableContext context) { Integer sentCount = 0; Boolean hitLimit = false; for (Lead ld : leadListToCallout) { if (Limits.getCallouts() == Limits.getLimitCallouts()) { hitLimit = true; break; } // perform callout try{ //-- Whatsapp_Opt_in__c == false, then send 'templatecallout1' data to hit the API-- if (!ld.Whatsapp_Opt_in__c) { lang.code = data1.code__c; lang.policy = data1.policy__c; temp.language = lang; temp.name = data1.name__c; temp.namespace = data1.namespace__c; tempbody.to = ld.MobileYM__c; tempbody.ttl = data1.ttl__c; tempbody.type = data1.type__c; tempbody.template = temp; template.body = tempbody; string Jsonbody = JSON.serialize(template); Httprequest request = new HttpRequest(); Http http = new Http(); request.setMethod('POST'); string jsonString = data1.url__c + '?bot='+data1.bot__c; request.setEndpoint(jsonString); request.setHeader('Content-Type', 'application/json'); request.setHeader('x-auth-token', data1.x_auth_token__c); request.setBody(Jsonbody); HttpResponse response = http.send(request); System.debug('Whatsapp false - request is: '+request); } //--Whatsapp_Opt_in__c == true, then send 'templatecallout2' data to hit the API-- else{ lang.code = data2.code__c; lang.policy = data2.policy__c; temp.language = lang; temp.name = data2.name__c; temp.namespace = data2.namespace__c; tempbody.to = ld.MobileYM__c; tempbody.ttl = data2.ttl__c; tempbody.type = data2.type__c; tempbody.template = temp; template.body = tempbody; string Jsonbody = JSON.serialize(template); Httprequest request = new HttpRequest(); Http http = new Http(); request.setMethod('POST'); string jsonString = data2.url__c + '?bot='+data2.bot__c; request.setEndpoint(jsonString); request.setHeader('Content-Type', 'application/json'); request.setHeader('x-auth-token', data2.x_auth_token__c); request.setBody(Jsonbody); HttpResponse response = http.send(request); System.debug('Whatsapp true - request is: '+request); } } catch (Exception e) { System.debug('Error::'+e.getMessage()); } // Track total leads processed sentCount++; } if (hitLimit) { // Need to chain this queueable to finish processing. First clean up // the list of leads needing a callout by removing all those that have // been sent already for (Integer index = 0; index < sentCount; index++) { leadListToCallout.remove(0); } // Now ensure the remainder get processed by simply re-enqueuing this // queueable with its adjusted state System.enqueueJob(this); } } }
Note: If you get an error while trying to edit the queueable apex class, check this out: Error 'This Apex class has batch or future jobs pending or in progress' (salesforce.com)