[SalesForce] Using Batch and Queueable causing Too many queueable jobs added to the queue: 2

I'm going to try and provide a blueprint of the code that I have in my production org.

Batch

global class EventBatchJob implements Database.Batchable<Event>, Database.Stateful, Database.AllowsCallouts, Schedulable {

    global List<Event> start(Database.BatchableContext bc){
        // make a callout to get list of list of events from external web service
        return API.getEvents();
    }

    global void execute(Database.BatchableContext bc, List<Event> scope) {
        for(Event e : scope){
            RegistrantSyncQueueable esync = new RegistrantSyncQueueable();
            esync.event = e;
            esync.offset = 0;
            System.enqueueJob(esync);
        }
    }

    global void finish(Database.BatchableContext bc) {
    }

    public static void run(){
        Type t = Type.forName('EventBatchJob');
        Database.Batchable< sObject > batchClass = ((Database.Batchable< sObject >) t.newInstance());
        Database.executeBatch(batchClass, 1);
    }
}

Queueable

public class RegistrantSyncQueueable implements Queueable, Database.AllowsCallouts {

    private Integer lim = 1000;
    public Integer offset = 0;
    public Event event;

    public void execute(QueueableContext qc){
        // make a callout to get registrants (with limit and offset, paginated data) for event
        List<Registrant> registrants = event.getRegistrants(lim, offset);

        // logic to process and save data

        if(registrants.size() < lim){
            // reached last page
        } else {
            // enqueue another job for next page
            RegistrantSyncQueueable esync = new RegistrantSyncQueueable();
            esync.event = event;
            esync.offset = offset + lim;
            if(!Test.isRunningTest()) {
                System.enqueueJob(esync);
            }
        }
    }
}

I'm using a batch size of 1 for my batch job and Queueable class has only one child Queueable. Now, this code randomly gives following error

Too many queueable jobs added to the queue: 2

Is it possible that the batch job tries to queue RegistrantSyncQueueable and an existing running instance of RegistrantSyncQueueable tries to download next page and enqueues another instance of RegistrantSyncQueueable to cause this error?

I'm not much sure about the limits of using Batch and Queueable classes together. Any help is appreciated.

Best Answer

You can only execute or enqueue one job from a job, as noted in Governor Limits on System.enqueueJob in Asynchronous Apex – Documentation Wrong?

As a simple alternative to your current approach, you can set the job size to 1:

Database.execute(myBatch, 1);

I see you are already doing that in your run method, which can be simplified to:

Database.executeBatch(new EventBatchJob(), 1);

And in your script you can call:

EventBatchJob.run();