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.