Skip to content

Instantly share code, notes, and snippets.

@JitendraZaa
Last active October 30, 2023 11:54
Show Gist options
  • Save JitendraZaa/bf5c987e86b7d6dc081d285699483189 to your computer and use it in GitHub Desktop.
Save JitendraZaa/bf5c987e86b7d6dc081d285699483189 to your computer and use it in GitHub Desktop.
Framework to fix - Salesforce Governor Limit of 100 jobs in Flex Queue
/**
* @Author : Jitendra Zaa
* @Date : Apr 21 2019
* Framework to fix limit of 100 Batch Apex in Queue
* */
public class BatchApexFramework implements Schedulable{
private static Integer availableBatchLimit = null;
//DO NOT Call this method in loop. It will cause repetative SOQL and DML
public static void submitBatch(Object batchClassInstance, Integer scopeSize){
AggregateResult[] groupedResults = [Select Count(Id) FROM AsyncApexJob Where Status = 'Holding'];
String exp0 = String.valueOf(groupedResults[0].get('expr0'));
availableBatchLimit = 100-Integer.valueOf(exp0);
if(availableBatchLimit > 0){
Database.batchable<sObject> b = (Database.batchable<sObject>)batchClassInstance;
Database.executeBatch(b, scopeSize);
}else{
String s = JSON.serialize(batchClassInstance);
BatchQueue__c q = new BatchQueue__c();
q.Batch_Size__c = scopeSize;
q.object__c = s;
q.Class_Name__c = String.valueOf(batchClassInstance).split(':')[0];
insert q;
}
}
public void execute(SchedulableContext SC) {
Integer availableLimit = 0;
AggregateResult[] groupedResults = [Select Count(Id) FROM AsyncApexJob Where Status = 'Holding'];
String exp0 = String.valueOf(groupedResults[0].get('expr0'));
availableLimit = 100-Integer.valueOf(exp0);
//We can spawn 50 async apex in single transaction
if(availableLimit > 50){
availableLimit = 50;
}
List<BatchQueue__c> lstBatch_StatusUpdate = new List<BatchQueue__c>();
if(availableLimit > 0){
List<BatchQueue__c> lstBatch = [Select
Batch_Size__c,
object__c ,
Class_Name__c
FROM
BatchQueue__c
Where
Status__c = 'Queued'
OR
Status__c = 'Failed'
LIMIT :availableLimit ];
if(!lstBatch.isEmpty()){
for(BatchQueue__c q : lstBatch){
try{
Type t = Type.forName(q.Class_Name__c);
Object des_Obj = JSON.deserialize (q.object__c,t);
Database.batchable<sObject> b = (Database.batchable<sObject>)des_Obj;
q.Job_Id__c = Database.executeBatch(b, Integer.valueOf(q.Batch_Size__c));
q.Status__c = 'Completed';
}catch(Exception e){
q.status__c = 'Failed';
q.note__c = e.getMessage()+'\n'+e.getStackTraceString();
}
lstBatch_StatusUpdate.add(q);
}
}
}
if(lstBatch_StatusUpdate.isEmpty()){
//TO DO - Get 7 days old BatchQueue records and purge them
}else{
update lstBatch_StatusUpdate;
}
}
}
// Use below code snippet to schedule Batch submitter to run every 15 minutes
System.schedule('BatchApexFramework 1', '0 0 * * * ?', new BatchApexFramework());
System.schedule('BatchApexFramework 2', '0 15 * * * ?', new BatchApexFramework());
System.schedule('BatchApexFramework 3', '0 30 * * * ?', new BatchApexFramework());
System.schedule('BatchApexFramework 4', '0 45 * * * ?', new BatchApexFramework());
// Use below code to submit Batch Apex using this framework
//Batch Demo is Batch Apex Class that needs to be executed
BatchDemo b = new BatchDemo('some value');
BatchApexFramework.submitBatch(b,1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment