Is it possible to queue a queueable apex job from a scheduled apex job?

I am attempting to implement a piece of scheduled apex which can work in an org with remarkably long computation time, meaning only a few hundred records can be operated on in a single context before the CPU time limit is hit. The basic idea is to enqueue queueable apex from a scheduled class and have that queued apex class call itself again if it needs to.

I currently have in place a class which is scheduled to run nightly, the execute() of which looks like (some names changed to protect the innocent)

global void execute(SchedulableContext SC) {
    System.enqueueJob(new QueueableApexClassName());
    //do stuff
}

Then the execute() of QueueableApexClassName() is

Boolean empty;

global void execute(QueueableContext SC) {
    empty = false;
    DoStuff();
    if (empty) System.enqueueJob(new QueueableApexClassName());
}

Empty is a boolean which is set in the DoStuff() method, to indicate there are no further need to enqueue jobs as the queries have returned empty (thus there are no more records to operate upon).

I cannot exactly deploy this willy-nilly to this remarkably large org, and test methods don’t cut it in the dev org. Will this work, or will I get an error once I try to run it?

Answer

You can do essentially what you’re asking, but there’s a couple of precautions you’ll want to take.

First, you’ll want to create an “on/off” switch that allows you to shut down your queueables should they happen run amuck. Should that occur, you’ll need some way of preventing them from continually spawning new jobs. You can easily do this by creating a class that checks the value of a custom setting. Your schedulable and queuables then checks a boolean that’s been set on a utility class before it queues up another instance of the queueable.

You’ll also want to check limits so you don’t try to fill up your flex queue with too many pending jobs. Your method would look something like this:

@future
private static void tryToQueue()
{
    if(!MyAppConfigSupport.appEnabled) return; 
       // This is your On/off switch
    try
    {
        if((Limits.getLimitQueueableJobs() - Limits.getQueueableJobs() > 0) && (!empty)) 
         // I suspect your criteria is !empty

            System.enqueueJob(new QueueableApexClassName();
    }
    catch(Exception ex)
    {
        // The exception would be because of hitting limits, so... 
        // you could wait for next request...
        // or maybe try using another instance of scheduled Apex for 2 min later?
    }
}

Attribution
Source : Link , Question Author : user28144 , Answer Author : crmprogdev

Leave a Comment