Apex – How to Specify Batch Size

apexgovernorlimitsvisual-workflow

I have some custom apex that I am invoking from a flow. The flow is sending a list of lists. The sub-list is a group of 5 sObjects with all the necessary fields to create new records.
So I have a parent list where each item in the list is a list of 5 custom sObjects. I want to perform a DML operation to insert these records in batches of 5 records. I do NOT want salesforce to group these DML calls into the standard bulkification batch size of 200, because I have other processes running on insert for this custom object that will fail for 200 records…I want to initiate this triggered process only on 5 records at a time, and independently for each of 5 records. Here is my code:

public class NewAffiliations {
    public class FlowInputWrapper {
        @InvocableVariable(required=true)
        public List<NU__Affiliation__c> affiliations;
    }
    
    @InvocableMethod(label='New Affiliations')
    public static void createAffiliationDetails(List<FlowInputWrapper> inputList) {
        Integer iterater = 0;
        for(FlowInputWrapper batches : inputList) {
            Savepoint sp = Database.setSavepoint();
            Database.insert(batches.affiliations);
            System.debug('Iterater' + iterater);
        }
    }
}

As you can see, I am performing the DML insert in a loop. inputList is the parent list, and batches represents each child list that contains 5 records. The desired outcome is that after each insert statement, the governor limits would reset so as to make all my triggered processes successful (note that the triggered processes are managed code from some apps we have installed, and therefore I do not have access to modify / fix the triggered code).

Some research indicated that the setSavepoint would cause a new transaction, therefore resetting governor limits. Is this true? Because I am getting a soql limit exceeded (it seems that the soql statements are adding up for each iteration).

How can I force a new transaction and reset of governor limits? How can I prevent salesforce from batching into chunks of 200, so that I can do 5 records like I want?

Best Answer

You're going to have to break the transaction boundary if you want a fresh set of governor limits. A basic structure that might work is a chaining Queueable, which you could use to do custom chunking as you have described. Note that your flow will not be able to know whether the operations succeed or fail once you make this change.

public with sharing class MyQueueable implements Queueable
{
    final List<SObject> records;
    public MyQueueable(List<SObject> records)
    {
        this.records = records;
    }
    public void execute(QueueableContext context)
    {
        // put in a kill switch
        
        List<SObject> toProcess = new List<SObject>();
        while (toProcess.size() < 5 && !records.isEmpty())
            toProcess.add(records.remove(0));
        
        // operate on toProcess
        
        if (!records.isEmpty())
            system.enqueueJob(new MyQueueable(records));
    }
}

Any time you use a self chaining Queueable implementation, it is highly recommended you add some Custom Setting which can terminate the jobs and prevent runaway recursion.