Apex more than 50 Queueble jobs
Why don't you use Queueable to process a 'Queue' of Order's?
As per the docs:
No limit is enforced on the depth of chained jobs, which means that you can chain one job to another job and repeat this process with each new child job to link it to a new child job. For Developer Edition and Trial organizations, the maximum stack depth for chained jobs is 5, which means that you can chain jobs four times and the maximum number of jobs in the chain is 5, including the initial parent queueable job.
This means you can use a list of SObjects as the 'queue' and then process them one by one until you get to the bottom of your chain. I've included an example of how you might do this.
global class NSStatusOrderCronSC implements Schedulable {
global void execute(SchedulableContext sc)
{
String norder;
String IdOpp;
List<Opportunity> opList = [SELECT Id FROM Opportunity Where StageName != 'Cerrado Ganado' AND StageName != 'Cancelado'];
List<Order> acList = [SELECT Pedido__c, Oportunidad__c FROM Order WHERE Pedido__c != null AND Oportunidad__c in :opList];
if(!acList.isEmpty()){
ID jobID = System.enqueueJob(new NSQueuebleJob(acList));
}
}
public class NSQueuebleJob implements Queueable, Database.AllowsCallouts {
private List<Order> orders;
public NSQueuebleJob(List<Order> orders)
{
this.orders = orders;
}
public void execute(QueueableContext qc)
{
Order order = orders.remove(0);
// do whatever you intended to do
// still more to process?
if(orders.size() > 0)
{
ID jobID = System.enqueueJob(new NSQueuebleJob(orders));
}
}
}
}
One of the approach could be to make a Queueable job to make few requests per execution to external endpoint and then process all the returned data. For example:
public class NSQueuebleJob implements Queueable, Database.AllowsCallouts {
private Map<id, String> OpportunitiesToProcess;
public NSQueuebleJob(Map<Id, String> inputOpportunities){
OpportunitiesToProcess = inputOpportunities;
}
public void execute(QueueableContext context) {
Map<Id, String> response_map = new Map<Id, String>();
Http http = new Http();
for(Id opportunity_id : OpportunitiesToProcess) {
String endpoint = constructURL(opportunity_id, OpportunitiesToProcess.get(opportunity_id));
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
HttpResponse response = http.send(request_instance);
responseMap.put(opportunity_id, response.getBody());
}
for(Id opportunity_id : response_map) {
//Logic to update some fields + collect all changes
}
//Logic to perform a DML regarding previously updated fields
}
}
In the given example, you can pass few records into your queueable job:
List<Opportunity> opList = [SELECT Id FROM Opportunity Where StageName != 'Cerrado Ganado' AND StageName != 'Cancelado'];
List<Order> acList = [SELECT Pedido__c, Oportunidad__c FROM Order WHERE Pedido__c != null AND Oportunidad__c in :opList];
Map<Id, String> queueable_job_params = new Map<Id, String>();
for(Order ac : acList)
{
IdOpp = ac.Oportunidad__c;
norder = ac.Pedido__c;
if(!acList.isEmpty()){
queueable_job_params.put(ac.Oportunidad__c, ac.Pedido__c);
ID jobID =
}
if (queueable_job_params.size() >= 20) {
System.enqueueJob(new NSQueuebleJob(queueable_job_params));
queueable_job_params.clear();
}
}
if (!queueable_job_params.isEmpty()) {
System.enqueueJob(new NSQueuebleJob(queueable_job_params));
}
In this case, you might decide which number of records should be passed into the single instance of queueable job execution. In case if there are a lot of records included -- it would be more wise to use an apex batch job.
Another approach could be Chaining -- basically pass all of the records into Queueable job, but process only as many, as you can based on your Heap Size/ Callout amount/ Total Callout Duration limit(s) per single execution.