0

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?

1 Answer 1

2

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.

2
  • Thank you so much for this solution. I had never heard of Queueable Chaining before. Very helpful. This did exactly what I was hoping for. Commented Jun 15, 2023 at 20:03
  • 1
    Don't forget about the Custom Setting. It is imperative you be able to kill these jobs across the entire org , preferably in one easy step, and definitely without a deployment.
    – Adrian Larson
    Commented Jun 16, 2023 at 0:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .