65

Using the salesforce GUI it seams impossible to schedule a job every 15 minutes. Or more than once a day.

Schedule Job GUI

1

6 Answers 6

74

Jobs cannot be scheduled in increments smaller than one hour. Please read the documentation to learn about how you can schedule jobs that run in more complex patterns than the GUI allows.

In Apex, you can schedule four jobs to every hour, staggered 15 minutes apart:

System.schedule('Scheduled Job 1', '0 0 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 2', '0 15 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 3', '0 30 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 4', '0 45 * * * ?', new ScheduledClass());
4
  • 7
    and consider use of Developer Console to execute said Apex via 'execute anonymous apex'.
    – cropredy
    Commented May 30, 2014 at 18:41
  • The shorter version listed here does not work for apex cron
    – fehays
    Commented Sep 11, 2014 at 16:33
  • hi, where should i add this? in the scheduler class? thanks Commented Aug 12, 2016 at 2:46
  • I would try to avoid using up 4 of the allowed 100 scheduled batch jobs to achieve this. My answer below shows how to run it once and have each run schedule the next one for 15 minutes later.
    – MikeA
    Commented Mar 13, 2021 at 13:00
28

@Christian is correct, but you can combine all that into a single line to be more efficient.

System.schedule('Scheduled Job 1', '0 0,15,30,45 * * * ?', new ScheduledClass());

Edit

It appears I was incorrect, you can only use comma separated lists for units hours or larger. Minutes and seconds does not support a comma separated list, so it appears you are stuck with either scheduling 4 jobs like below, or getting creative by scheduling a following job in the Finish() method of your batch class.

System.schedule('Scheduled Job 1', '0 0 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 2', '0 15 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 3', '0 30 * * * ?', new ScheduledClass());
System.schedule('Scheduled Job 4', '0 45 * * * ?', new ScheduledClass());
3
  • Can you go as far with this technique as to schedule to run every 10 seconds? Perhaps you could comment/answer on that on this question salesforce.stackexchange.com/questions/37306/….
    – Keith C
    Commented May 30, 2014 at 14:14
  • Hmmmmm. interesting. I think it would let you schedule it, but I highly doubt it will be successful as the job isn't guaranteed to actually run when its scheduled, its just queued I believe. Commented May 30, 2014 at 14:33
  • 2
    I get an error System.schedule('Scheduled Job 1', '0 0,15,30,45 * * * ?', new NotiflyTrialExpiration()); System.StringException: Seconds and minutes must be specified as integers: 0 0,15,30,45 * * * ? Commented Aug 8, 2014 at 15:02
13

I've been playing around with something like this to achieve periodic execution of an operation with granularity as low as 1 or 2 minutes. It's a class that implements the Schedulable interface. In its "execute" method, it simply reschedules a new instance of itself some time in the future (specified by the "intervalMinutes" parameter, then aborts its currently scheduled instance, and invokes a future method or launches a batch job to do the actual work. The nice thing about this approach is that it doesn't require multiple scheduled Apex jobs (there's never more than one scheduled at a time). It seems to be working quite well. See any potential drawbacks to this approach?

global without sharing class JobRunner implements Schedulable {
    Integer intervalMinutes;
    public JobRunner(Integer intervalMinutes) {
        this.intervalMinutes = intervalMinutes;
    }
    public void execute(SchedulableContext sc) {
        // Re-schedule ourself to run again in "intervalMinutes" time
        DateTime now  = DateTime.now();
        DateTime nextRunTime = now.addMinutes(intervalMinutes);
        String cronString = '' + nextRunTime.second() + ' ' + nextRunTime.minute() + ' ' + 
            nextRunTime.hour() + ' ' + nextRunTime.day() + ' ' + 
            nextRunTime.month() + ' ? ' + nextRunTime.year(); 
        System.schedule(JobRunner.class.getName() + '-' + now.format(), cronString, new JobRunner(intervalMinutes));
        // Abort the current job
        Id jobId = sc.getTriggerId();
        System.abortJob(jobId);     
        // Launch a batch job or call a future method to do the actual work
        Database.executeBatch(new SomeBatchJob());
    }
}
4
  • 4
    Drawback I see in this approach is - it will show each Apex job as aborted in the Apex job log
    – Prasanna
    Commented Feb 9, 2015 at 10:47
  • 2
    Good point. I guess it comes down to trade offs. If you really need granular scheduling down to one or two minutes, the platform doesn't really allow you to achieve it any other way AFAIK, unless you want to tie up a bunch of your scheduled Apex slots with multiple scheduled executions.
    – tlfu
    Commented Feb 10, 2015 at 11:42
  • I'm curious if there's a way to address the drawback @eprasu pointed out? For example, can the 'aborted' status of the job be overwritten with a 'success' status once we've programmatically determined everything went according to plan?
    – smohyee
    Commented Jul 24, 2015 at 16:28
  • Like @tlfu mentioned, this is a good solution if you don't want to tie up multiple slots per job. For example, running two jobs every minute (2*60>100) already brings you over the limit for scheduled jobs. Using tlfu's method, you only consume 2 jobs. I actually ended up going with this. Commented May 10, 2019 at 22:41
5

I've always found it difficult to schedule a job using Cron Expression. It always takes me a while to form a corn expression.

Recently I came across an online tool to generate cron expression called as Cron Maker. It's a superb tool which can be used to generate cron expression on the basis of minutes, hours, Daily, Weekly, Monthly and Yearly.

Refer below snapshot:

enter image description here

2
  • 3
    Regrettably, you can't schedule in increments smaller than an hour in Salesforce Cron Jobs. See the Accepted Answer for the relevant workaround.
    – sfdcfox
    Commented Apr 20, 2017 at 5:38
  • @sfdcfox Thanks for correcting. Updated the answer. Commented Apr 20, 2017 at 6:30
5

I would try to avoid using up 4 of the allowed 100 scheduled batch jobs to achieve this.

Just schedule the next run from the finish method of the batch class, and set it off from anonymous Apex.

I have this in my finish method, to schedule a job in 15 mins time, with a batch size of 20 and a job name of 'My Batch Job'. The check for isRunningTest() prevents the test failing due to the job already being scheduled:

if(!Test.isRunningTest()) {
  System.scheduleBatch(new MyBatchClass(), 'My Batch Job', 15, 20);
}

Start the job from anonymous Apex with

Id batchInstanceId = Database.executeBatch(new MyBatchClass(), 20);

Docs for System.scheduleBatch() are here https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_system.htm#apex_methods_system_system

0

Piggy-backing off other people's answers, here's a slightly more dynamic way of scheduling classes. It just requires the name of the class and every nth minute you want the class to run.

//You just need to modify these two variables
Integer everyNthMinute = 5;
String nameOfSchedulableClass = 'YourSchedulableClassNameHere';


Integer counter = 1;
for(Integer minute=0;minute<60;minute++){
    if(Math.mod(minute,everyNthMinute)==0){
        String scheduleName = nameOfSchedulableClass + String.valueOf(counter);
        String cronPattern  = '0 '+ String.valueOf(minute) +' * * * ?';
        System.schedule(scheduleName,cronPattern, (Schedulable)Type.forName(nameOfSchedulableClass).newInstance());
        counter++;
    }
}


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .