We have a batch class AccountDeactivationBatch
from whose finish()
method we run 3 more batches, including AccountDeactivationBatch
again, but with new set of Ids. These new set of Ids are all children account IDs of all records that were processed in this batch. This goes on till no eligible child records are fetched from database.querylocator().
Following is sample code:
public class AccountDeactivationBatch implements Database.Batchable<sObject>, Database.Stateful {
public Set<Id> accountIdSet = new Set<Id>();
public Set<Id> newAccountIdSet = new Set<Id>(); //to maintain next level children acc id.
public AccountDeactivationBatch(Set<Id> accountIdSet){
this.accountIdSet = accountIdSet;
}
public Database.QueryLocator start(Database.BatchableContext bc) {
String query = 'select Active__c, from Account ' +
'where Send_To_ABC__c = true ' +
'and Active__c = true and ParentId in : accountIdSet';
return Database.getQueryLocator(query);
}
public void execute(Database.BatchableContext bc, List<Account> records)
{
public List<Account> accountList = new List<Account>();
newAccountIdSet.clear();
for(Account acc : records){
acc.Active__c = false;
accountList.add(acc);
newAccountIdSet.add(acc.id); //Maintaining children account ids
that were fetched from query. To be used in query of next batch.
}
update records;
}
public void finish(Database.BatchableContext bc){
//Run Contact batch.
ContactDeactivationBatch contactDeactivationBatch = new ContactDeactivationBatch(accountIdSet);
Id contactBatchId = Database.executeBatch(contactDeactivationBatch);
//Run User batch.
UserDeactivationBatch userDeactivationBatch = new UserDeactivationBatch(accountIdSet);
Id userBatchId = Database.executeBatch(userDeactivationBatch);
//Calling this same batch again, but with next level child account IDs
if(newAccountIdSet.size() > 0){ //Need this check to avoid recrusion.
AccountDeactivationBatch accountDeactivationBatch = new AccountDeactivationBatch(newAccountIdSet);
Id accountBatchId = Database.executeBatch(accountDeactivationBatch);
}
}
}
Following are the queries in this case: 1. We may run into 'Attempted to schedule too many concurrent batch jobs in this org' error. Can this error be avoided using Apex flex queues. 2. Is the query for AsyncApexJob table required to fetch Status='Queued' jobs or flex queues will resolve this? 3. If we write SOQL on AsyncApexJob, is there a chance to hit SOQL exception? 4. What are other possible limits that could be exceeded in this case?
Appreciate any help here. Thanks in advance.
I had referred this help article regarding this issue.