[SalesForce] Is it possible to call Batch from a future call

I was wondering if it is possible to call a batch from a @future method? The reason I am asking as you may have guessed is because I am trying to call batches from a trigger. Eg: Leads are inserted then call batch after insert trigger on Leads.

I know it is possible to call Database.executeBatch, however there is a limitation to the number of batches you can send. With current FlexQueue implementation you can invoke up to 100 batch calls per a transaction.

But my question is what if I need to send more than that per a transaction?

I was thinking of calling a @future method and in that method I call the batch, but I get this error:

System.AsyncException: Database.executeBatch cannot be called from a
batch start, batch execute, or future method.

Pseudocode:

trigger leadTrigger on Lead(after insert) { 
    //some code 
    TriggerHelper.callTheBatch(); 
} 

public without sharing class TriggerHelper { 
    @future 
    public static void callTheBatch() { 
        MyBatchClass myBatchClass1 = new MyBatchClass(); 
        Id batchId = database.executebatch(myBatchClass1, 50); 
    } 
} 

Any suggestion or idea?

Best Answer

There's a number of ways to exceed 100 callouts per transaction using asynchronous code, but trying to call a batch from a future method doesn't even make sense, given all the sanctioned ways we've been given to do so. Here's a few things you could do:

Use @future methods

Break up your lists into batches of about 50 or so, and every 50 callouts just call your future method. You need to use callout=true to allow callouts, like this:

@future(callout=true) public static void doCallouts(Id[] recordIds) {
    ...
}

Use Queueable classes

Break up your lists into batches of about 50 or so, and every 50 callouts just call a Queueable. It'd look like this:

System.enqueueJob(new CalloutQueueable(Id[] recordIds));

Use Batchable classes... Responsibly

Dan Appleman made mention of using a retryable mechanism, and I've built one personally. The general idea is that you create a custom object that stores details about each callout you want to perform asynchronously. Then, you set up a scheduler that runs hourly, checks to see if any new integrations need to be processed, and if so, kicks off the batchable process. You can adjust the scheduler to be as frequent as you'd like, but by allowing a bit of pooling of the requests before trying to process them results in more efficient use of system resources. Other systems may not be able to handle this type of batching though, so smaller/more frequent batches may be required.