0

I have a scenario where I need a better approach. I am trying the Queueable class for the first time. I have an AcccountTriggerhandler on which I am calling the Queueable class on onAfterUpdate. Once the Queueable is executing I need to update the same account. But it is actually going into the recursive trigger. So that I have added a static variable to prevent it from executing which is doing the job. But in some scenarios, some of the fields are getting updated with old values due to old jobs. Some time fields are not getting updated

I know this is a little big line of code. I would like to get to know where am I doing it wrong.

Accounttrigger.apxt

if( trigger.isAfter )
{
   
    if( trigger.isUpdate )
    {
        // Added the static variable from running twice
        if(!ContactIntegrationQueueable.runOnce){ //
            objHandler.onAfterUpdate( trigger.new, trigger.oldMap );//CallingAccounttriggerHandler
        }
    }
}

AccounttriggerHandler.apxc

 public void onAfterUpdate( List<Account> newAccounts, Map<Id, Account> oldAccountMap )
{
    syncData();
    //Here is where I am calling the ContactIntegrationQueueable
    System.enqueueJob(new ContactIntegrationQueueable(oldAccountMap,newAccounts));
    performActionofPBCompanyCreatedOrEditedandHL(newAccounts, oldAccountMap, FALSE);
}

Once the Job runs I need to update the newAccount

Queueable Class

public with sharing class KeyContactIntegrationQueueable implements Queueable,Database.AllowsCallouts{
List<Account> accListToHandle = new List<Account>();
List<Account> queuedAccount = new List<Account>();
Map<Id, Account> mapOfOldAccount = new Map<Id, Account>();
Map<Id, Account> queuedmapOfOldAccount = new Map<Id, Account>();
Boolean isUpdate;
public static Boolean runOnce = false;
final Integer MAX_LIMIT = 50;

public KeyContactIntegrationQueueable(Map<Id, Account> mapIdToAccount,List<Account> accountRecords) {
   for(Integer i=0;i<accountRecords.size();i++){
        if(i<MAX_LIMIT){
            this.accListToHandle.add(accountRecords[i]);
        }else{
            this.queuedAccount.add(accountRecords[i]);
        }
    }
    Integer count=0;
    for(Id key:mapIdToAccount.keySet()){
        if(count<MAX_LIMIT){
            this.mapOfOldAccount.put(key,mapIdToAccount.get(key));
        }else{
            this.queuedmapOfOldAccount.put(key,mapIdToAccount.get(key));
        }
        count++;
    }
    List<Account> accListToHandleAfterUpdate = KeyContactIntegrationUtils.callBitter(this.accListToHandle,this.mapOfOldAccount);  
    this.isUpdate = true;
}
public void execute(QueueableContext context) {
    List<Contact> keyContacts = new List<Contact>();
    List<Contact> keyContactToInsert = new List<Contact>();
    List<Account> accountToUpdate = new List<Account>();
    for(Account objAccount : accListToHandle) {
        if(keyContacts <>NUll&&keyContacts.isEmpty()){
            keyContacts =  KeyContactIntegrationContactHelper.GetKeyContactsFromD(String.ValueOf(objAccount.get(System.Label.Clearbit_Domain)),objAccount.Id);
        }
        if(keyContacts <>NUll){
        keyContactToInsert.addAll(keyContacts);
        }
        if(isUpdate){
            Account cloneAccount = objAccount.clone(true,false,true,true);
            cloneAccount.call_clearbit__c = false;
            accountToUpdate.add(cloneAccount);
        }
           
    }
    try{
        INSERT keyContactToInsert;
    }catch(Exception excp){
        if( !(excp.getMessage().contains('DUPLICATES_DETECTED') || excp.getMessage().contains('already exist'))){
            System.debug('->> Contact already existing');
        }
    }
    //This is the portion which i would like avoid if we have a better option
    if(isUpdate){
        runOnce=!runOnce;
        //UPDATE accountToUpdate;//Commented this code cause it is breaking some of the field from updating
        runOnce=!runOnce;
    }
    if(queuedAccount.size()>0 && isUpdate){
        System.enqueueJob(new 
  KeyContactIntegrationQueueable(queuedmapOfOldAccount,queuedAccount));
    }
    
}

}

I have added the isUpdate variable to differentiate from the update and insert(which need to be implemented) of the account. Please let know if there are any good approach I should deal this with.

4
  • the queueable class always executes in a separate transaction so runOnce makes no sense. To manage state across queueables you should use sobject field values
    – cropredy
    Jun 9, 2021 at 22:07
  • @cropredy I am getting too many jobs added when running test class. Do you think the code which I wrote is the one making this issue
    – NBR
    Jun 10, 2021 at 13:21
  • You have to test chained queueables differently; see salesforce.stackexchange.com/questions/181233/…
    – cropredy
    Jun 10, 2021 at 14:35
  • I have a test class that is inserting and updating the same account. I am calling queaueble class onafterupdate and onafterinsert which is causing the issue. Is there any solution for that
    – NBR
    Jun 10, 2021 at 14:49

0

You must log in to answer this question.

Browse other questions tagged .