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
Thayalan Guhathashan 11Thayalan Guhathashan 11 

Error - CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY:AccountTrigger: System.LimitException: Apex CPU time limit exceeded:--

Hi , I have this handler methods on after update trigger, why do I get CPU time limit exceed exception


trigger AccountTrigger on Account (before update, after insert, after update ) 
{
   
    if( AccountTriggerHandler.runFlag )
      {
        AccountTriggerHandler.runFlag = false;
       
        if( Trigger.isUpdate && Trigger.isAfter )
        {
            AccountTriggerHandler.handleAfterUpdate( Trigger.newMap, Trigger.oldMap );
            AccountTriggerHandler.forceSync(Trigger.new,Trigger.oldMap);
            
        }
        
        AccountTriggerHandler.runFlag = true;
    }

}










public class AccountTriggerHandler 
{
    public static boolean runFlag = true;
    
     public static void  forceSync(List<Account> acc, Map<id,Account> oldaccounts)
     {
        Set<Id> accIds = new Set<Id>();
        MAP<Id,Guarantor__c> guarantorMap = new MAP<Id,Guarantor__c>();
        List<Security_Holder__c> sclisttoUpdate= new List<Security_Holder__c>();
        List<Certificate__c> certlisttoUpdate= new List<Certificate__c>();
        
 
         
        for ( Account a:acc )
         {
           Account oldAcc = oldaccounts.get(a.Id);
           if((a.Last_Updated_Date_Non_Integration_User__c != null) && (a.lastmodifieddate != oldAcc.lastmodifieddate)) 
           {
             accIds.add(a.id);
            } 
         }
         
        if(accIds.size()> 0) 
        {
        for (Account accs: [
             select id,
             (SELECT id,Force_Sync__c FROM Guarantors__r),  (SELECT id,Force_Sync__c FROM GuaranteeProviders__r) , (SELECT id,Force_Sync__c FROM Certificates__r), (SELECT id,Force_Sync__c FROM Security_Holders__r)
             from Account 
             where (Id in :accIds )]) {
           
            if(accs.Guarantors__r.size() > 0)
            {
            for(Guarantor__c gc:accs.Guarantors__r)
            { gc.Force_Sync__c = true;
              guarantorMap.put(gc.id,  gc);
            }
            }
        
           if(accs.GuaranteeProviders__r.size() > 0)
            {
            for(Guarantor__c gcs:accs.GuaranteeProviders__r)
            { gcs.Force_Sync__c = true;
              guarantorMap.put(gcs.id,  gcs);
            }
            }
             
            if(accs.Security_Holders__r.size() > 0)
            {   
              for(Security_Holder__c sc:accs.Security_Holders__r)
            { sc.Force_Sync__c = true;
              sclisttoUpdate.add(sc);
            }
            }
             
              if(accs.Certificates__r.size() > 0)
            { 
             for(Certificate__c cr:accs.Certificates__r)
            { cr.Force_Sync__c = true;
              certlisttoUpdate.add(cr);
            } 
            }
         }
        }
        if (!guarantorMap.isEmpty()) {
             Database.update(guarantorMap.values(), false);
           }
            
             
            
        if (!sclisttoUpdate.isEmpty()) {
            Database.update(sclisttoUpdate, false); 
           } 
         
         if (!certlisttoUpdate.isEmpty()) {
            Database.update(certlisttoUpdate, false); 
        }  
    }  
    
   
  
  // Thayalan finish
    public static void handleAfterInsert( List<Account> insertedAccounts )
    {
        updateNonIntegrationAuditFields( insertedAccounts );
    }
    
    public static void handleAfterUpdate( Map<Id, Account> updatedAccounts, Map<Id, Account> oldAccounts )
    {
        updateNonIntegrationAuditFields( updatedAccounts.values() );
        updatePendingApplicationFields( updatedAccounts , oldAccounts);
    }
    
    private static void updateNonIntegrationAuditFields( List<Account> accounts )
    {
        Set<Id> userIds = new Set<Id>();
        for( Account a: accounts )
        {
            userIds.add( a.LastModifiedById );
        }
        
        Map<ID, User> users = new Map<Id, User>([Select Id, Integration_User__c from User
                           where id in: userIds
                           and Integration_User__c = false]);
        
        List<Account> accountsToUpdate = new List<Account>();
        for( Account a: accounts )
        {
            if( users.containsKey( a.LastModifiedById ) )
            {
                Account b = new Account( Id=a.Id );
                b.Last_Updated_by_Non_Integration_User__c = a.LastModifiedDate;
                b.Last_Updated_Date_Non_Integration_User__c = a.LastModifiedById;
                accountsToUpdate.add(b);
            }        
        }
        
        if( accountsToUpdate.size() > 0 )
        {
            update accountsToUpdate;
        }

    }
}
David Zhu 🔥David Zhu 🔥
I believe property runFlag is designed to prevent AFTER trigger running recursively.
You may change the code a bit:

trigger AccountTrigger on Account (before update, after insert, after update ) 
{
   
    if( AccountTriggerHandler.runFlag )
      {
        if( Trigger.isUpdate && Trigger.isAfter )
        {
            AccountTriggerHandler.handleAfterUpdate( Trigger.newMap, Trigger.oldMap );
            AccountTriggerHandler.forceSync(Trigger.new,Trigger.oldMap);
            AccountTriggerHandler.runFlag = false;
        }
       
    }

}
 
Thayalan Guhathashan 11Thayalan Guhathashan 11

Hi David Zhu 🔥,

after removing the ( before update, after insert) still getting the same problem when child objects get updated in bulk
David Zhu 🔥David Zhu 🔥
Can you try code below?

trigger AccountTrigger on Account (before update, after insert, after update ) 
{
   
    if( AccountTriggerHandler.runFlag )
      {
        if( Trigger.isUpdate && Trigger.isAfter )
        {
             AccountTriggerHandler.runFlag = false;
            AccountTriggerHandler.handleAfterUpdate( Trigger.newMap, Trigger.oldMap );
            AccountTriggerHandler.forceSync(Trigger.new,Trigger.oldMap);
            
        }
       
    }

}

 
Thayalan Guhathashan 11Thayalan Guhathashan 11
Tht is the one I have it- 

trigger AccountTrigger on Account (before update, after insert, after update ) 
{
    if( Trigger.isUpdate && trigger.isAfter)
    {
      SynclogHandler.createLog(Trigger.new,Trigger.oldMap);
    }
    if( AccountTriggerHandler.runFlag )
      {
        AccountTriggerHandler.runFlag = false;
        if( Trigger.isInsert && Trigger.isAfter )
        {
            AccountTriggerHandler.handleAfterInsert( Trigger.new );
        }
    
        if( Trigger.isUpdate && Trigger.isAfter )
        {
            AccountTriggerHandler.handleAfterUpdate( Trigger.newMap, Trigger.oldMap );
            AccountTriggerHandler.forceSync(Trigger.new,Trigger.oldMap);
            
        }
        
        AccountTriggerHandler.runFlag = true;
    }

}
David Zhu 🔥David Zhu 🔥
If you take a close look of the code snippet I provide, you need to remove AccountTriggerHandler.runFlag = true; in the last line of the your code. 
This will prevent AFTER UPDATE trigger running recursively.