0

I have a Scheduler apex class that is facing CPU time limit exceeded error. Can someone please help me to by pass this error here? Please find my Scheduler apex here.

global class PartnerLeadtoAccountScheduler implements Schedulable {

global void execute(SchedulableContext sc) {

    map < Id, Account > mapAccount = new map < Id, Account > ();
    set < string > checkDuplicateEmail = new set < string > ();
    set < String > emailEntry = new set < String > ();
    Map < String,Account> emailToAccountMap = new Map < String,Account>();

    List < Partner_Lead__c > partnerLead = [Select id, Business_Nature__c, Company_Name__c, Contact_Number__c, Contact_Person__c, Date__c, Designation__c, Email_Address__c, Package_Plan__c, OwnerId, CP_Name_Text__c, createddate FROM Partner_Lead__c WHERE Email_Address__c != Null order by createddate asc];
    system.debug('--partnerLead--' + partnerLead);
    /*
    List < Partner_Lead__c > partnerLead1 = [Select id, Business_Nature__c, Company_Name__c, Contact_Number__c, Contact_Person__c, Date__c, Designation__c, Email_Address__c, Package_Plan__c, OwnerId, CP_Name_Text__c, createddate FROM Partner_Lead__c WHERE Email_Address__c != Null order by createddate asc];
    */

    Map < string, schema.RecordTypeInfo > rtName = schema.SObjectType.Account.getRecordTypeInfosByName();
    Id rt = rtName.get('Lead').getRecordTypeId();
    Id rt1 = rtName.get('Merchant').getRecordTypeId();

    mapAccount = new Map < Id, Account > ([SELECT id, Subscription_Email__c, Channel_Partner__c, Closure_Source__c, RecordTypeId FROM Account]);
    for (account acc: mapAccount.values()) {
        checkDuplicateEmail.add(acc.Subscription_Email__c);
        emailToAccountMap.put(acc.Subscription_Email__c, acc);
    }

    system.debug('mapAccount' + mapAccount);

    Map < String, Partner_Lead__c[] > assotiactedServiceByEmail = new Map < String, Partner_Lead__c[] > ();
    List < Partner_Lead__c > partnerleadToBeUpdated = new List < Partner_Lead__c > ();
    List < Account > accountList = new List < Account > ();
    List < Account > updatedAccountList = new List < Account > ();

    Map < string, Account > mapSAB = new Map < string, Account > ();
    Map < string, Account > mapUpdatedSAB = new Map < string, Account > ();
    Partner_Lead__c plead;
    for (Partner_Lead__c pl: partnerLead) {
        plead = new Partner_Lead__c(id = pl.id);
        if (!checkDuplicateEmail.contains(pl.Email_Address__c)) {
            if(pl.Contact_Person__c!=null){
            Account acc = new Account();
            acc.LastName = pl.Contact_Person__c;
            acc.RecordTypeId = rt;
            acc.Business_Type__c = pl.Business_Nature__c;
            acc.Company_Name__c = pl.Company_Name__c;
            acc.Phone = pl.Contact_Number__c;
            acc.Designation__c = pl.Designation__c;
            acc.Subscription_Email__c = pl.Email_Address__c;
            acc.AccountSource = 'Channel Partner';
            acc.Channel_Partner__c = True;
            acc.Package_Plan__c = pl.Package_Plan__c;
            acc.CP_Name__c = pl.OwnerId;
            acc.Cp_Date__c = DateTime.valueOf(pl.createddate).Date();
            acc.CP_Name_Text__c = pl.Company_Name__c;

            accountList.add(acc);  
            }
        }
        if (checkDuplicateEmail.contains(pl.Email_Address__c)) {

            Id rt2 = rt;
            Id rt3 = rt1;

            Account ac = emailToAccountMap.get(pl.Email_Address__c);
            system.debug('--ac--' + ac);
            system.debug('--rt3--' + rt3);
            system.debug('--rt2--' + rt2);
            updatedAccountList.add(ac);
            if (mapAccount.get(ac.Id).Closure_Source__c == 'Organic' && mapAccount.get(ac.Id).RecordTypeId == rt3) {
                mapAccount.get(ac.Id).Channel_Partner__c = true;
                mapAccount.get(ac.Id).Closure_Source__c = 'Channel Partner';
                mapAccount.get(ac.Id).CP_Name__c = pl.OwnerId;
                mapAccount.get(ac.Id).CP_Name_Text__c = pl.Company_Name__c;
                mapAccount.get(ac.Id).Cp_Date__c = pl.Date__c;
                mapAccount.get(ac.Id).Package_Plan__c = pl.Package_Plan__c;

            } else if (mapAccount.get(ac.Id).Closure_Source__c != 'Organic' && mapAccount.get(ac.Id).RecordTypeId == rt2) {
                mapAccount.get(ac.Id).Channel_Partner__c = true;
                mapAccount.get(ac.Id).CP_Name__c = pl.OwnerId;
                mapAccount.get(ac.Id).CP_Name_Text__c = pl.Company_Name__c;
                mapAccount.get(ac.Id).Package_Plan__c = pl.Package_Plan__c;
                mapAccount.get(ac.Id).Cp_Date__c = pl.Date__c;
            }
        }
    }
    List<Partner_Lead__c> pllist=new list<Partner_Lead__c>();
if(accountList!=null){
    for (Account acc1: accountList) {
        system.debug('--acc1--' + acc1);
        mapSAB.put(acc1.Subscription_Email__c, acc1);
        system.debug('--mapSAB--' + mapSAB);
    }
}
    for (Account acc1: updatedAccountList) {
        system.debug('--acc1--' + acc1);
        mapUpdatedSAB.put(acc1.Subscription_Email__c, acc1);
        system.debug('--mapUpdatedSAB--' + mapUpdatedSAB);
    }

    if (!mapSAB.values().isEmpty()) {
        insert mapSAB.values();
        system.debug('--mapSAB.values()--' + mapSAB.values());        
    }
    update mapAccount.values();

    //Populating Account lookup on partner lead object
    for(Partner_Lead__c pl :partnerLead){
        system.debug('--mapSAB acc id--'+mapSAB.get(pl.Email_Address__c));
        if(mapSAB.get(pl.Email_Address__c)!=null){
            pl.Account__c=mapSAB.get(pl.Email_Address__c).id;               
            system.debug('--pl--'+pl);
        }
        else if(mapUpdatedSAB.get(pl.Email_Address__c)!=null){
            pl.Account__c=mapUpdatedSAB.get(pl.Email_Address__c).id;                
            system.debug('--pl--'+pl);
        }
        if (!(emailEntry.contains(pl.Email_Address__c))) {
            pl.Updated__c = true;
            //updateSet.add(pl.Id);
            emailEntry.add(pl.Email_Address__c);
            system.debug('--IF-cnt-' + pl.Email_Address__c);
            /*
            if (mapSAB.get(pl.Email_Address__c) != null) {
                plead.Account__c = mapSAB.get(pl.Email_Address__c).id;
                system.debug('--plead--' + plead);
            }
            */
        } else {
            system.debug('--else-cnt-' + pl.Email_Address__c);
            pl.Conflict__c = true;
            // conflictSet.add(pl.Id);
        } 


     pllist.add(pl);   
     system.debug('--pllist!!!!--'+pllist);  
    }
    /*    
    Integer cnt = 0;
    for (Partner_Lead__c pl: partnerLead) {
        cnt++;
        plead = new Partner_Lead__c(id = pl.id);
        system.debug('--IF-Condition----' + checkDuplicateEmail.contains(pl.Email_Address__c) + ' && ' + !emailEntry.contains(pl.Email_Address__c));
        system.debug('--emailEntry-----' + emailEntry);
        if (!(emailEntry.contains(pl.Email_Address__c))) {
            plead.Updated__c = true;
            emailEntry.add(pl.Email_Address__c);
            system.debug('--IF-cnt-' + pl.Email_Address__c);
        } else {
            system.debug('--else-cnt-' + pl.Email_Address__c);
            plead.Conflict__c = true;
        }
        partnerleadToBeUpdated.add(plead);
    }
    system.debug('--accountList--' + accountList);
    */      
    //update partnerleadToBeUpdated;
    update pllist;
    system.debug('--pllist--' + pllist);
}

}

  • 1
    how many times your scheduler call? – Ratan Paul Dec 10 '15 at 6:32
  • 1
    @Ratan Everyday night at 10PM – SFDC shaikh Dec 10 '15 at 6:38
  • 1
    I would suggest optimize you code and give a try check still you are getting error. for ex. you did 4 times describe call, you can describe only once and get the record id based on recordType name Map < string, schema.RecordTypeInfo > – Ratan Paul Dec 10 '15 at 7:20
  • How much records are processed by those queries? Probably you need to do a batch job, that starts by schedule Then It would not hit any limit in single execute method if you specify right amount of records – kurunve Dec 10 '15 at 7:54
  • You really need to refactoring this code. You have SOQL in a for loop, repeated describe calls that could be made once, and non selective SOQL calls (you query the whole account table). Keep in mind that SOQL calls are generally very time intensive so reducing those as much as possible will help. – techbusinessman Dec 10 '15 at 8:23
3

You have used SOQL inside for loop, you have called schema 4 times for the same reason, you have unnecessary loops. Let me rectify your code.

global class PartnerLeadtoAccountScheduler implements Schedulable {

    global void execute(SchedulableContext sc) {

        map < Id, Account > mapAccount = new map < Id, Account > ();

        set < string > checkDuplicateEmail = new set < string > ();
        set < Id > updateSet = new set < Id > ();
        set < Id > conflictSet = new set < Id > ();
        set < String > emailEntry = new set < String > ();

Good enough!

List < Partner_Lead__c > partnerLead = [Select id, Business_Nature__c, Company_Name__c, Contact_Number__c, Contact_Person__c, Date__c, Designation__c, Email_Address__c, Package_Plan__c, OwnerId, CP_Name_Text__c, createddate FROM Partner_Lead__c WHERE Email_Address__c != Null];
                    system.debug('--partnerLead--' + partnerLead);

List < Partner_Lead__c > partnerLead1 = [Select id, Business_Nature__c, Company_Name__c, Contact_Number__c, Contact_Person__c, Date__c, Designation__c, Email_Address__c, Package_Plan__c, OwnerId, CP_Name_Text__c, createddate FROM Partner_Lead__c WHERE Email_Address__c != Null order by createddate asc];

You dont really need 2 identical queries. Replace this with -

List < Partner_Lead__c > partnerLead = [Select id, Business_Nature__c, Company_Name__c, Contact_Number__c, Contact_Person__c, Date__c, Designation__c, Email_Address__c, Package_Plan__c, OwnerId, CP_Name_Text__c, createddate FROM Partner_Lead__c WHERE Email_Address__c != Null order by createddate asc];

Next,

Map < string, schema.RecordTypeInfo > rtName = schema.SObjectType.Account.getRecordTypeInfosByName();
        Id rt = rtName.get('Lead').getRecordTypeId();

Map < string, schema.RecordTypeInfo > rtName1 = schema.SObjectType.Account.getRecordTypeInfosByName();
        Id rt1 = rtName.get('Merchant').getRecordTypeId();

mapAccount = new Map < Id, Account > ([SELECT id, Subscription_Email__c, Channel_Partner__c, Closure_Source__c, RecordTypeId FROM Account]);
for (account acc: mapAccount.values()) {
            checkDuplicateEmail.add(acc.Subscription_Email__c);
        }

Do not call schema everytime you need something from it. Call it once, use it as many times you want and create a map of email to Account from your SOQl query here. Use it later.

Map < string, schema.RecordTypeInfo > rtName = schema.SObjectType.Account.getRecordTypeInfosByName();
Id rt = rtName.get('Lead').getRecordTypeId();
Id rt1 = rtName.get('Merchant').getRecordTypeId();

mapAccount = new Map < Id, Account > ([SELECT id, Subscription_Email__c, Channel_Partner__c, Closure_Source__c, RecordTypeId FROM Account]);
for (account acc: mapAccount.values()) {
            checkDuplicateEmail.add(acc.Subscription_Email__c);
            emailToAccountMap.put(acc.Subscription_Email__c, acc);
        }

Then the following code is good enough only you have to remove the SOQL from the loop and use the map(emailToAccountMap) I created above.

Map < String, Partner_Lead__c[] > assotiactedServiceByEmail = new Map < String, Partner_Lead__c[] > ();

        List < Partner_Lead__c > partnerleadToBeUpdated = new List < Partner_Lead__c > ();
        List < Account > accountList = new List < Account > ();
        List < Account > updatedAccountList = new List < Account > ();

        Map < string, Account > mapSAB = new Map < string, Account > ();
        Map < string, Account > mapUpdatedSAB = new Map < string, Account > ();
        Partner_Lead__c plead;
        for (Partner_Lead__c pl: partnerLead) {
            plead = new Partner_Lead__c(id = pl.id);
            if (!checkDuplicateEmail.contains(pl.Email_Address__c)) {

                Account acc = new Account();
                acc.LastName = pl.Contact_Person__c;
                acc.RecordTypeId = rt;
                acc.Business_Type__c = pl.Business_Nature__c;
                acc.Company_Name__c = pl.Company_Name__c;
                acc.Phone = pl.Contact_Number__c;
                acc.Designation__c = pl.Designation__c;
                acc.Subscription_Email__c = pl.Email_Address__c;
                acc.AccountSource = 'Channel Partner';
                acc.Channel_Partner__c = True;
                acc.Package_Plan__c = pl.Package_Plan__c;
                acc.CP_Name__c = pl.OwnerId;
                acc.Cp_Date__c = DateTime.valueOf(pl.createddate).Date();
                acc.CP_Name_Text__c = pl.Company_Name__c;
                // system.debug('--acc--'+acc.Id);
                //plead.Updated__c=true;
                accountList.add(acc);  

                // partnerleadToBeUpdated.add(plead); 

            }
            if (checkDuplicateEmail.contains(pl.Email_Address__c)) {

                Id rt2 = rt;
                Id rt3 = rt1;


                Account ac = emailToAccountMap.get(pl.Email_Address__c); //Instead of SOQL querying here, use the map I spoke above. 
                updatedAccountList.add(ac);
                Account tempAcc = mapAccount.get(ac.Id);
                if (tempAcc.Closure_Source__c == 'Organic' && tempAcc.RecordTypeId == rt3) {
                    tempAcc.Channel_Partner__c = true;
                    tempAcc.Closure_Source__c = 'Channel Partner';
                    tempAcc.CP_Name__c = pl.OwnerId;
                    tempAcc.CP_Name_Text__c = pl.Company_Name__c;
                    tempAcc.Cp_Date__c = pl.Date__c;
                    tempAcc.Package_Plan__c = pl.Package_Plan__c;
                    //plead.Updated__c=true;
                    //system.debug('--plead.Updated__c--'+plead.Updated__c);
                    //mapAccount.get(ac.Id).Updated__c = true;
                    //inserFlag = false;
                    //updateFlag = true;
                    //partnerleadToBeUpdated.add(plead); 
                } else if (tempAcc.Closure_Source__c != 'Organic' && tempAcc.RecordTypeId == rt2) {
                    tempAcc.Channel_Partner__c = true;
                    tempAcc.CP_Name__c = pl.OwnerId;
                    tempAcc.CP_Name_Text__c = pl.Company_Name__c;
                    tempAcc.Package_Plan__c = pl.Package_Plan__c;
                    mapAccount.get(ac.Id).Cp_Date__c = pl.Date__c;
                    //plead.Updated__c=true;
                    //system.debug('--plead.Updated__c--'+plead.Updated__c);
                    //mapAccount.get(ac.Id).Updated__c = true;
                    //inserFlag = false;
                    //updateFlag = true;  
                    //partnerleadToBeUpdated.add(plead); 
                }
            }
        }
        List<Partner_Lead__c> pllist=new list<Partner_Lead__c>();
    if(accountList!=null){
        for (Account acc1: accountList) {
            system.debug('--acc1--' + acc1);
            mapSAB.put(acc1.Subscription_Email__c, acc1);
            system.debug('--mapSAB--' + mapSAB);
        }
    }
        for (Account acc1: updatedAccountList) {
            system.debug('--acc1--' + acc1);
            mapUpdatedSAB.put(acc1.Subscription_Email__c, acc1);
            system.debug('--mapUpdatedSAB--' + mapUpdatedSAB);
        }

        if (!mapSAB.values().isEmpty()) {
            insert mapSAB.values();
            system.debug('--mapSAB.values()--' + mapSAB.values());

        }


        update mapAccount.values();

Next, you dont need 2 different loops to update the Partner Leads. Technically you are looping over same set of records and updating them twice.

//Populating Account lookup on partner lead object
        for(Partner_Lead__c pl :partnerLead){
            //system.debug('--mapSAB acc id--'+mapSAB.get(pl.Email_Address__c));
            //system.debug('--mapAccount acc id--'+mapAccount.get(pl.Email_Address__c));

Account tempAcc1 = mapSAB.get(pl.Email_Address__c); Account tempAcc2 = mapUpdatedSAB.get(pl.Email_Address__c); if(tempAcc1 !=null){ pl.Account__c=tempAcc1.id;
system.debug('--pl--'+pl); } else if(tempAcc2 !=null){ pl.Account__c=tempAcc2.id;
system.debug('--pl--'+pl); }

         pllist.add(pl);   
         system.debug('--pllist!!!!--'+pllist);  
        }

        //List < Partner_Lead__c > pllist = new list < Partner_Lead__c > ();
        Integer cnt = 0;
        for (Partner_Lead__c pl: partnerLead1) {
            cnt++;
            plead = new Partner_Lead__c(id = pl.id);
            system.debug('--IF-Condition----' + checkDuplicateEmail.contains(pl.Email_Address__c) + ' && ' + !emailEntry.contains(pl.Email_Address__c));
            system.debug('--emailEntry-----' + emailEntry);
            if (!(emailEntry.contains(pl.Email_Address__c))) {
                plead.Updated__c = true;
                //updateSet.add(pl.Id);
                emailEntry.add(pl.Email_Address__c);
                system.debug('--IF-cnt-' + pl.Email_Address__c);
            } else {
                system.debug('--else-cnt-' + pl.Email_Address__c);
                plead.Conflict__c = true;
                // conflictSet.add(pl.Id);
            }
            partnerleadToBeUpdated.add(plead);
        }
        system.debug('--accountList--' + accountList);

        update partnerleadToBeUpdated;
        update pllist;

Replace the above with this.

//Populating Account lookup on partner lead object
        for(Partner_Lead__c pl :partnerLead){
            system.debug('--mapSAB acc id--'+mapSAB.get(pl.Email_Address__c));
            //system.debug('--mapAccount acc id--'+mapAccount.get(pl.Email_Address__c));
            if(mapSAB.get(pl.Email_Address__c)!=null){
                pl.Account__c=mapSAB.get(pl.Email_Address__c).id;               
                system.debug('--pl--'+pl);
            }
            else if(mapUpdatedSAB.get(pl.Email_Address__c)!=null){
                pl.Account__c=mapUpdatedSAB.get(pl.Email_Address__c).id;                
                system.debug('--pl--'+pl);
            }
            if (!(emailEntry.contains(pl.Email_Address__c))) {
                pl.Updated__c = true;
                //updateSet.add(pl.Id);
                emailEntry.add(pl.Email_Address__c);
                system.debug('--IF-cnt-' + pl.Email_Address__c);
            } else {
                system.debug('--else-cnt-' + pl.Email_Address__c);
                pl.Conflict__c = true;
                // conflictSet.add(pl.Id);
            }
         pllist.add(pl);   
         system.debug('--pllist!!!!--'+pllist);  
        }
        update pllist;
        system.debug('--pllist--' + pllist);

P.S - Please don't blindly copy the codes. There could be mismatch in curly brackets as I have edited this in Notepad++.

  • Thanks @Santanu for your reply But I am getting error EXCEPTION: System.StringException: Invalid id: fsadfsafs@fasfsa.com STACKTRACE: External entry point LINE: -1 COLUMN: -1 – SFDC shaikh Dec 10 '15 at 10:28
  • emailToAccountMap this map should be Map<String, Account> not Map<Id, Account> – Santanu Halder Dec 10 '15 at 11:04
  • Still getting Apex cpu time limit exceeded error Line No 105[Below //Populating Account lookup on partner lead object] – SFDC shaikh Dec 10 '15 at 12:39
  • How many records are you getting from that 2 SOQL queries? – Santanu Halder Dec 10 '15 at 12:44
  • I have updated the code to access the maps less by taking into temp variable. Try now. – Santanu Halder Dec 10 '15 at 12:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.