+ Start a Discussion
A.ZaykovA.Zaykov 

APEX CPU time limit exceeded, opportunity team members trigger.

Hi guys,

I don't understand why I get "System.LimitException: Apex CPU time limit exceeded" on mass update.

Basically I want to count opportunity team members with specific role and store the counter in a custom field on opportunity level.
 
Trigger roleUpdateOnly on OpportunityTeamMember (after update) {
  
  
  Set<Id> setOpptyIdsUpdateOnly = new Set<Id>();
  
    
    for(OpportunityTeamMember optm: Trigger.new) {
        if(trigger.isUpdate){
        
         String oldRole = trigger.OldMap.get(optm.Id).TeamMemberRole;
             if(oldRole == 'specific role' || optm.TeamMemberRole == 'specific role') {
                setOpptyIdsUpdateOnly.add(optm.OpportunityId);
             }
           }
        }  
  
  List<Opportunity> listOpps= [Select id,Counter_specific_role__c ,
 (Select id from OpportunityTeamMembers WHERE TeamMemberRole = 'specific role')
 from Opportunity where Id in : setOpptyIdsUpdateOnly];

  for(Opportunity opp :listOpps) {
   
   opp.Counter_specific_role__c = opp.opportunityTeamMembers.size();
  }
  update listOpps; 
   
}


Thanks in advance.
 
James LoghryJames Loghry
This could be caused by a few different items. The first one is simply that you have so much data in your org, that this trigger kind of chugs along and surpasses the CPU limit.

The second could be that you're running into a recursive situation where since you're updating opportunities, it updates all the opportunity members "under the covers" and keeps executing over and over and over.

To alleviate that second issue, you could try checking to see if the role actually changed, which *should* only fire the trigger one time:
 
Trigger roleUpdateOnly on OpportunityTeamMember (after update) {
  
  
  Set<Id> setOpptyIdsUpdateOnly = new Set<Id>();
  
    for(OpportunityTeamMember optm: Trigger.new) {
        if(trigger.isUpdate){
        
         String oldRole = trigger.OldMap.get(optm.Id).TeamMemberRole;
         //Your trigger was basically saying that "Update the opportunity any time an opportunity member is updated where either the old role or the current role is specific role.
        //I added a update check into the same statement, that says "Update the opportunity any time the role changes AND the old role was either specific role or the current role is specific role.
             if(oldRole != optm.TeamMemberRole && (oldRole == 'specific role' || optm.TeamMemberRole == 'specific role')) {
                setOpptyIdsUpdateOnly.add(optm.OpportunityId);
             }
           }
        }  
  
  List<Opportunity> listOpps= [Select id,Counter_specific_role__c ,
 (Select id from OpportunityTeamMembers WHERE TeamMemberRole = 'specific role')
 from Opportunity where Id in : setOpptyIdsUpdateOnly];

  for(Opportunity opp :listOpps) {
   
   opp.Counter_specific_role__c = opp.opportunityTeamMembers.size();
  }
  update listOpps; 
   
}

Hopefully that helps.
A.ZaykovA.Zaykov
Thanks, James. Unfortunately, it did not solve the problem.
NForceNForce
Hi, Apex CPU time limit exceeded is due to the inner query
"  List<Opportunity> listOpps= [Select id,Counter_specific_role__c ,
 (Select id from OpportunityTeamMembers WHERE TeamMemberRole = 'specific role')
from Opportunity where Id in : setOpptyIdsUpdateOnly]"

It seems like you have a huge number of records in your Org. For every Opportunity, it's fetching all the OpportunityTeamMembers with 'Specific Role'. Try to add extra conditions to narrow down the number of OpportunityTeamMembers items. Or else
create 2 maps, one for Opportunity and one for OpportunityTeamMembers. One disadvantage of this approach is 1 query will be added to the total SOQL limit.