I usually include a few helper methods in any Schedulable
class that needs to run at a given time as determined by Apex logic that's more complex than a simple cron expression. You can then call Database.executeBatch()
from your Schedulable
class's execute
method:
public class Schedule_SomethingAwesome implements Schedulable {
public static final String JOBNAME = 'Schedule_SomethingAwesome';
public void execute(SchedulableContext sc) {
Database.executeBatch(new AwesomeBatchJob(), 200);
}
public static void scheduleMe(DateTime runtime) {
unscheduleMe();
runtime = (runtime!=null) ? runtime : System.now().addMinutes(15);
if ( runtime >= System.now() ) {
DateTime next = runtime;
String cron = next.second() + ' ' + next.minute() + ' ' + next.hour() + ' ' +
next.day() + ' ' + next.month() + ' ? ' + next.year();
Id jobId = System.schedule(JOBNAME, cron, new Schedule_SomethingAwesome());
// do something with the jobId, like keep track of the job in a custom setting, perhaps?
}
}
public static void unscheduleMe() {
for ( CronTrigger ct : [select Id from CronTrigger where CronJobDetail.Name like :(JOBNAME+'%')] ) {
System.abortJob(ct.Id);
}
}
}
I find this useful because then I can kill kill the job before it runs if I need to. Alternatively, you can use System.scheduleBatch()
as you suggested, by specifying the length of time in minutes until the job should fire:
public static void scheduleBatch(DateTime runtime) {
DateTime now = System.now();
Integer delay = Integer.valueOf((runtime.getTime()-now.getTime())/1000/60);
System.scheduleBatch(new AwesomeBatchJob(), 'AwesomeBatchJob'+System.now().getTime(), delay);
}