You need to sign in to do that
Don't have an account?
TinkerMe
Resolving Apex CPU Time Limit Exceeded Error
Hi,
I am trying to resolve a conflict from the existing Apex code. We have enrolments coming in from a different system but some of these are not being pushed to salesforce because of Apex CPU time limit exceeded error. it is identified that these are coming from one of the codes. Any recommendations to improve the code to avoid this error?
Trigger:
Handler:
I am trying to resolve a conflict from the existing Apex code. We have enrolments coming in from a different system but some of these are not being pushed to salesforce because of Apex CPU time limit exceeded error. it is identified that these are coming from one of the codes. Any recommendations to improve the code to avoid this error?
Trigger:
trigger UpdateLocalObjectsFromEnlighten on enlighten__Enrollment__c (after insert, after update) { if(TriggerUtilities.bPreventTriggers == true) { return; } UpdateLocalObjectsFromEnHandler handler = new UpdateLocalObjectsFromEnHandler(); handler.doIt(trigger.new, trigger.oldMap); }
Handler:
public with sharing class UpdateLocalObjectsFromEnHandler { private string debugInfo = ''; private void addDebug(string inf) { debugInfo += inf + '\n'; } public void doIt(List<enlighten__Enrollment__c> newVals, Map<id, enlighten__Enrollment__c> oldVals) { // all items to update // we need the first and last activities related to each enrolment, if available Map<string, ActivityInfo> activities = new Map<string, ActivityInfo>(); enlighten__Course_Activity__c[] cas = [select enlighten__Activity_Time__c, enlighten__Enrollment__c, enlighten__Module__r.name from enlighten__Course_Activity__c where enlighten__Enrollment__c in :newVals and (enlighten__Module__r.name = 'Module 1 Quiz' or enlighten__Module__r.name like '%final exam%')]; addDebug('found ' + cas.size() + ' records'); for(enlighten__Course_Activity__c ca : cas) { addDebug(ca.enlighten__Enrollment__c); if(!activities.containsKey(ca.enlighten__Enrollment__c)) { activities.put(ca.enlighten__Enrollment__c, new ActivityInfo()); } if(ca.enlighten__Module__r.name == 'Module 1 Quiz') { activities.get(ca.enlighten__Enrollment__c).Started = ca.enlighten__Activity_Time__c; addDebug('Module 1 Quiz @ ' + ca.enlighten__Activity_Time__c); } else if(ca.enlighten__Module__r.name.toLowerCase().contains('final exam')) { activities.get(ca.enlighten__Enrollment__c).Completed = ca.enlighten__Activity_Time__c; addDebug('Final Exam @ ' + ca.enlighten__Activity_Time__c); } else { addDebug(ca.enlighten__Module__r.name + ' not found'); } } Set<id> toFind = new Set<id>(); //System.debug('-------------- start'); for(enlighten__Enrollment__c i : newVals) { if(!toFind.contains(i.id)) { toFind.add(i.id); System.debug('********* ' + i.id); } } enlighten__Enrollment__c[] recs = [select id, enlighten__Contact__c, enlighten__Course_Score__c, enlighten__Percent_Complete__c, enlighten__Course_Enroll_Date__c, enlighten__Course_Complete_Date__c, enlighten__Status__c, enlighten__Course__r.enlighten__Course_ID__c, enlighten__Enroll_End_Date__c, enlighten__Course_Complete__c, enlighten__Last_Access__c from enlighten__Enrollment__c where id in: toFind]; //System.debug('-------------- ' + recs.size()); Set<string> CourseNames = new Set<string>(); Set<id> contacts = new Set<id>(); // Loop and find all the SF course names (removing dash as needed) // and related contacts for(enlighten__Enrollment__c e : recs) { if(e.enlighten__Course__c == null) { //System.debug('enlighten__Course__c does not have a value (1)'); continue; } string CourseName = e.enlighten__Course__r.enlighten__Course_ID__c; if(CourseName != '' && CourseName != null) { //System.debug('enlighten course name:' + CourseName); integer dash = CourseName.lastIndexOf('-'); if(dash > -1) { CourseName = CourseName.substring(0, dash).trim(); } if(!CourseNames.contains(CourseName)) { CourseNames.add(CourseName); //System.debug(CourseName); } if(!contacts.contains(e.enlighten__Contact__c)) { contacts.add(e.enlighten__Contact__c); } } else { //System.debug('CourseName from enlighten is empty or null'); } } // now get potential matches -- this might retrieve more than needed but will be filtered below List<Student_Course_List__c> scls = [select id, Student__c, course__c, course__r.name, Percent_Complete1__c, Percent_Grade__c, Number_Grade__c, Actual_End_Date__c, Actual_Start_Date__c, Scheduled_End_Date__c, Last_Access__c, Enlighten_Enrollment_ID__c, Course_Status__c from student_course_list__c where Course__r.name in: CourseNames and Student__c in: contacts]; //System.debug('=============SCL ==' + scls.size()); // create a composite key of student+course name Map<string, Student_Course_List__c> sclLookup = new Map<string, Student_Course_List__c>(); for(Student_Course_List__c scl: scls) { sclLookup.put(scl.Student__c + scl.course__r.name, scl); } Map<id, Student_course_list__c> toUpdate = new Map<id, Student_Course_List__c>(); // loop again and find any student courses registrations that match the enlighted update for(enlighten__Enrollment__c e : recs) { if(e.enlighten__Course__c == null) { //System.debug('enlighten__Course__c does not have a value (2)'); continue; } string cn = e.enlighten__Course__r.enlighten__Course_ID__c; if(cn != '' && cn != null) { integer dash = cn.lastIndexOf('-'); if(dash > -1) { cn = cn.substring(0, dash).trim(); } //System.debug('***********************************updating ' + cn); // update the fields if(sclLookup.containsKey(e.enlighten__Contact__c + cn)) { Student_Course_List__c item = sclLookup.get(e.enlighten__Contact__c + cn); addDebug('found ' + e.enlighten__Contact__c + cn + ' status is ' + item.Course_Status__c); if(item.Course_Status__c != 'Released') { item.Percent_Complete1__c = e.enlighten__Percent_Complete__c; item.Percent_Grade__c = e.enlighten__Course_Score__c; item.Number_Grade__c = e.enlighten__Course_Score__c; //item.Enrollment_Status__c = e.enlighten__Status__c; item.Actual_Start_Date__c = e.enlighten__Course_Enroll_Date__c; item.Scheduled_End_Date__c = e.enlighten__Enroll_End_Date__c; //item.Course_Completed__c = e.enlighten__Course_Complete__c; //item.Last_Access__c = e.enlighten__Last_Access__c; // not being used //item.Percent_Complete__c = e.enlighten__Percent_Complete__c; item.Enlighten_Enrollment_ID__c = e.id; //item.Course_Complete__c = e.enlighten__Course_Complete__c; // handled by formula ActivityInfo act = activities.get(e.id); if(act != null) { if(act.Started != null) { item.Activity_Started__c = act.Started; addDebug('setting Activity_Started__c ' + act.Started); } else { addDebug('no start date for ' + e.id); } if(act.Completed != null) { item.Activity_Completed__c = act.Completed; addDebug('setting Activity_Completed__c ' + act.Completed); } else { addDebug('no end date for ' + e.id); } } else { addDebug('not found for ' + e.id); } // if more than one update for this student course registration, use the most recent one toUpdate.put(item.id, item); //System.debug('updating SCR ' + item.id + ' contact ' + e.enlighten__Contact__c + ' ' + cn); } } else { addDebug('did not find ' + e.enlighten__Contact__c + cn); } } } // end for update toUpdate.values(); // now update number of courses on this day List<Student_Course_List__c> countCoursesEnrolled = new List<Student_Course_List__c>(); Map<string, integer> sums = new Map<string, integer>(); string lastKey = ''; string key = ''; integer courseCount = 0; scls = [select id, Student__c, Count_of_Courses_Enrolled__c, Enlighten_Enrollment_ID__r.enlighten__Course_Enroll_Date__c, Full_Time__c, Course__r.Course_Length_Days__c from student_course_list__c where Student__c in: contacts and Enlighten_Enrollment_ID__r.enlighten__Course_Enroll_Date__c != null and Asynchronous__c = true order by Student__c, Enlighten_Enrollment_ID__r.enlighten__Course_Enroll_Date__c]; integer totalRecs = scls.size(); integer recCount = 0; //System.debug('----totalRecs ' + totalRecs); // summarize by student + date + course length for(Student_Course_List__c s2 : scls) { Date dt = s2.Enlighten_Enrollment_ID__r.enlighten__Course_Enroll_Date__c; key = s2.student__c + String.valueOf(dt) + String.valueOf(s2.Course__r.Course_Length_Days__c); //System.debug('key=' + key); recCount++; if(key != lastKey || recCount == totalRecs) { if(key == lastKey) { courseCount++; } sums.put(lastKey, courseCount); courseCount = 0; } lastKey = key; //System.debug('lastKey=' + lastKey); courseCount++; } //System.debug('doing updates, if any==============='); // now go through and see if any of the values need to be updated for(Student_Course_List__c s2 : scls) { Date dt = s2.Enlighten_Enrollment_ID__r.enlighten__Course_Enroll_Date__c; key = s2.student__c + string.valueOf(dt) + String.valueOf(s2.Course__r.Course_Length_Days__c); //System.debug('key=' + key); integer sumVal = sums.get(key); //System.debug('sumVal=' + sumVal); if(s2.Count_of_Courses_Enrolled__c != sumVal) { s2.Count_of_Courses_Enrolled__c = sumVal; countCoursesEnrolled.add(s2); } } // Count_of_Courses_Enrolled if(countCoursesEnrolled.size() > 0) { update countCoursesEnrolled; } System.debug(debugInfo); } private class ActivityInfo { public string EnrolmentId { get; set;} public DateTime Started { get; set;} public DateTime Completed { get; set;} } }
2) Another thing is that, debug statements also takes reasonable processing time and avoid keeping debug lines until its not useful. I see lot of debug lines in the code.
3) SOQL dont have any impact with CPU time limit as salesforce excludes from the processing time.
4) Keep this trigger execution in asyncronous processing(Queuable Or future) so get better govorner limits if the code still requires lot of processing time.
A good article from salesforce to avoid CPU time limit: https://help.salesforce.com/apex/HTViewSolution?id=000232681&language=en_US
Choose this answer as best reply if it's helpful.
Thanks.