6

I am writing a chained batch process that will be called by another method via a Database.executeBatch() call that specifies the batch size. I am trying to figure out how to pass that same batch size along to the subsequent batches in the chain (which are invoked via another Database.executeBatch() call within the finish() method.

Is there a way to get the batch size of the current BatchableContext?

EDIT:

Thanks to @sfdcfox's advice, here is the final structure I ended up with, which is working great:

global class MyBatchClass implements Database.Batchable<sObject>, Database.Stateful
{
    String query;
    private Integer batchSize;

...

    global void execute(Database.BatchableContext BC, List<sObject> scope) 
    {
        if(batchSize == NULL || scope.size() > batchSize) batchSize = scope.size();

        //logic...
    }

    global void finish(Database.BatchableContext BC) 
    {
        if (batchSize == NULL) batchSize = 50; //just in case the first class didn't have any records to work on
        if( !test.IsRunningTest() ) //So that the chained batch doesn't break unit tests
        {
            Database.executeBatch(new MySecondBatchClass(),batchSize);
        }
    }
}
4

It's not ideal, but you could just pass the desired batch size for the scope parameter into the Batch constructor - See Passing Parameter to batch apex.

Another slight variation of that is to use Database.Stateful and then set a member variable to the largest size of the list you encounter in the execute method. As sfdcfox commented, if there aren't more than the scoped number of records then the count you get will be smaller than the scope. If you are chaining them then you might eventually end up with a scope of 1.

If you don’t specify Database.Stateful, all static and instance member variables are set back to their original values.
Source

4
  • I had thought of passing the parameter through the chain but as you say, it's not ideal. I like the second idea though, I'll definitely give that a try.
    – OBerm
    Jul 1 '16 at 1:33
  • 2
    @Dupe_jockey That works only if the batch has at least two iterations... otherwise the value might be smaller than the original request, if that matters.
    – sfdcfox
    Jul 1 '16 at 4:17
  • 1
    Database.Stateful is needed in both cases.
    – Keith C
    Jul 1 '16 at 7:45
  • @KeithC I was going off the docs that said static variables would be reset between executions. I figured it would be fine if the value was only set in the constructor. Jul 2 '16 at 21:20
3

I've done this in a chained batchable before:

public class MyBatchable implements Database.Batchable<SObject>, Database.Stateful {

    private Integer batchSize;

    public MyBatchable(Integer batchSize, ...) {
        this.batchSize = batchSize;
    }

    ...

    public void finish(Database.BatchableContext bc) {
        Database.executeBatch(new MyBatchable(batchSize, ...));
    }
}
5
  • Huh, that's exactly what I was going to recommend, though I've never used it. Glad to see it works in practice.
    – Adrian Larson
    Jun 30 '16 at 21:59
  • 1
    I agree that this works, I've actually done it before as well, but something about it seems intuitively off. My gut feeling was that this info should be available from within the batch, and I think Daniel's idea about looking for the size of the execution scope list will work (though it also feels a bit like a cheat) :)
    – OBerm
    Jul 1 '16 at 1:47
  • 1
    @Dupe_jockey Agree it doesn't feel right. Adding a public (and making the constructor private) static method that accepts the batch size and does the Database.executeBatch for both the initial and chained calls avoids having to pass the batch size twice and is a bit clearer.
    – Keith C
    Jul 1 '16 at 7:44
  • 1
    @Keith I think my unease stems from the fact that the call to initiate the run would have to include the batch size parameter twice: Database.executeBatch(new MyBatchClass(batchSize),batchSize); . It's the same info, so we should only need to include it one time.
    – OBerm
    Jul 1 '16 at 14:09
  • 1
    @Dupe_jockey Yeah certainly feels wrong. Hence the static method so the size is only passed once.
    – Keith C
    Jul 3 '16 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.