function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mario CMario C 

CPU limit issues on class that creates account contact and case

Ivecreated a class which gets called by an integration that creates an account, contact and case.

Unfortunately, I get CPU limit errors and I do not really know how to solve it. Any help would be much appreaciated.

Thanks!
 
public class HTTPChatContrSec {
  
        
    public HTTPChatContrSec(List<ID> x)
        
    {     

List<LC_chat__c> allChats = [Select id, extid__c,Existing_Member_Id__c,Existing_Lead_Id__c,Enquiry_Type__c, First_Name__c, Last_Name__c, Country__c, email_id__c, phone_no__c, notes__c, chat_id__c, chat_transcript__c, type_of_contact__c 
                          from lc_chat__c where id in :x limit 100];
        
        
        
    //define existing leads in chat__c and prepare for deletion 
        List<ID> leadIdToBeremoved = new List<ID>();
        List<lc_chat__c> leadChatRemovalList = New List<lc_chat__c>();
        List<Lead> leadRemovalList = New List<Lead>();

        for(lc_chat__c exLead: allChats){
            if(exLead.Type_of_Contact__c == 'Existing Lead'){
            leadIdToBeremoved.add(exLead.Existing_Lead_ID__c);
            leadChatRemovalList.add(exLead); 
        }//end of if
            } 
        delete leadChatRemovalList;
        
        List<Lead> leadToBeDeleted = [Select id from lead where id in :leadIdToBeremoved];
        
        for(Lead deletedLeads:leadToBeDeleted){
            leadRemovalList.add(deletedLeads);
        }
        delete leadRemovalList;
        
         //Existing Contact Case Creation Process
         List<sObject> newCases = new List<sObject>();
           for(lc_chat__c newChat:allChats){

            if(newChat.Type_of_Contact__c == 'Existing Member'){
        
                    
                	Case cs1 = new Case();
                    cs1.Subject = 'Lead Crushr Entry';
                    cs1.origin = 'Lead Crushr';
                    cs1.Description = newChat.notes__c + ' \n TRANSCRIPT: \n' + newChat.chat_transcript__c;
                    cs1.ContactId = newChat.Existing_Member_Id__c;
                    cs1.Type = newChat.Enquiry_Type__c;
                    cs1.Reason = 'Other';
            		//cs1.recordtypeid = SObjectType.Case.getRecordTypeInfosByDeveloperName().get('Master Record Type').getRecordTypeId();
            		cs1.Lead_Crushr_Record__c = newChat.id;
                
                	newCases.add(cs1);
            }//if condition for size() > 0 end here!
                	
            }
      
    
        
        

List<SObject> lstAccount = new List<SObject>(); 
//holds list of Contact
List<SObject> lstContacts = new List<SObject>();
//holds list of Cases
List<SObject> lstCase = new List<SObject>(); 
//final list for insertion
SObject[] sobjList = new List<SObject>();
//inserted records
List<ID> insList = new List<ID>();
           
String strInsertError = '';

//holds accountId and External Id in a Map
Map<String,String> accountContactMap = new Map<String,String>();
//holds contactId and External Id in a Map        
Map<String,String> contactCaseMap = new Map<String,String>();
 
//loop through the chats
for(Integer i=0; i<allChats.size();i++)
{
  Account accountObj = new Account();
  accountObj.lc_Id__c = allChats.get(i).extid__c; 
  accountObj.Name = allChats.get(i).last_name__c + ' Household';
  accountContactMap.put(accountObj.Name,accountObj.LC_ID__c);
  //finally add object to the list
  lstAccount.add(accountObj);
}
 
//loop through to create Contact record
for(Integer i=0;i<allChats.size();i++)
{
  Contact contactObj = new Contact(); 
  contactObj.LastName = allChats.get(i).last_name__c;
  contactObj.lc_ID__c = allChats.get(i).extid__c;
  contactObj.FirstName = allChats.get(i).first_name__c;
  contactObj.LeadSource = 'Lead Crushr';
  contactObj.Country_USE_ME__c = allChats.get(i).Country__c;
  contactObj.email = allChats.get(i).email_id__c;
  contactObj.phone = allChats.get(i).phone_no__c;
  contactObj.Newsletter__c = 'No';
  contactObj.Source_Type__c = 'Chat';
  contactCaseMap.put(contactObj.email,contactObj.lc_ID__c);


    
  // Create the parent reference.
  //check the Account Name in the map and retrieve the External Id from map
  if(accountContactMap.containsKey(allChats.get(i).last_name__c + ' Household'))
  {
   Account conReference = new Account(
   lc_Id__c =accountContactMap.get(allChats.get(i).last_name__c + ' Household')); 
   contactObj.Account = conReference;
      
  }  
  lstContacts.add(contactObj); 
}  
    
for(Integer i=0;i<allChats.size();i++)
{    
  Case caseObj = new Case(); 
  caseObj.Subject = 'Lead Crushr Entry';
  caseObj.origin = 'Lead Crushr';
  caseObj.Description = allChats.get(i).notes__c + ' \n TRANSCRIPT: \n \n' + allChats.get(i).chat_transcript__c;
  caseObj.Type = allChats.get(i).Enquiry_Type__c;
  caseObj.Reason = 'Other';
  caseObj.Lead_Crushr_Record__c = allChats.get(i).id;
  if(contactCaseMap.containsKey(allChats.get(i).email_id__c))
  {
   Contact casReference = new Contact(
   lc_Id__c =contactCaseMap.get(allChats.get(i).email_id__c)); 
   caseObj.Contact = casReference;

}
    lstCase.add(caseObj); 
       
}
  
    
//add account, contact and cases lists
sobjList.addAll(newCases);
sobjList.addAll(lstAccount);
sobjList.addAll(lstContacts);
sobjList.addAll(lstCase);


// Create the Account and the Contact in single DML.
Database.SaveResult[] results = Database.insert(sobjList);
// Check results.
for (Integer i = 0; i < results.size(); i++) {
  if (results[i].isSuccess()) 
  {
      insList.add(results[i].getId());
  System.debug('Successfully created ID: ' + results[i].getId());
  } 
  else 
  {
   System.debug('Error: could not create sobject ' + 'for array element ' + i + '.');
   strInsertError = 'The error reported was: ' + results[i].getErrors()[0].getMessage() + '\n';
   System.debug(strInsertError);
  }
} 
System.debug('strInsertError=' + strInsertError);
       
  
        
    }
                
            }

 
Best Answer chosen by Mario C
Alain CabonAlain Cabon
@Mario C : the CPU limit is for one transaction. The idea is to create new transactions but the only simple ways are a Future Method or the Queueable Apex. The second one could be better because you can monitor the status of the asynchronous treatment but a future method is often enough.

The big problem with future/queueable is the slowness waiting a slot for the excecution of the asynchronous treatment (sometime quite long) and the difficult rollback in case of problem.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_queueing_jobs.htm
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_invoking_future_methods.htm

Main code:
//add account, contact and cases lists
sobjList.addAll(newCases);
sobjList.addAll(lstAccount);

Queueable Apex: 
//add account, contact and cases lists
sobjList.addAll(lstContacts);
sobjList.addAll(lstCase);


Code more efficiently to avoid 'Apex CPU time limit exceeded':

Explore if your business allows you to do the operation asynchronously:
In some cases business process may not be real time and hence if there is a chance to make code execute in @future ,this will break the context and also the CPU time out limit for asynchronous process is 60seconds(6X of synchronous process).So, consider this if you're in trouble of hitting the limit.

https://help.salesforce.com/articleView?id=000232681&language=en_US&type=1