[SalesForce] How to run Apex code every 5 minutes in 2016

From a naive read of these questions and answers:

and given that the "Maximum number of Apex classes scheduled concurrently" limit is now 100, setting up 12 scheduled jobs 5 minutes apart seems like the simple (and durable – see the discussion in Scheduled batch jobs and durability) way of achieving this.

Are there any downsides to this approach given the platform as it is in 2016? Is there a compelling alternative?

(This is not an academic question – looks like we are going to have to do this to work-around a problem so looking for advice. The problem is that some getContentasPdf pages fail to render images stored in Attachments when executed in asynchronous code kicked off from a site. As this processing is asynchronous anyway, looking to execute it in the non-site context where it is known to work via this scheduled code and avoid future context-related surprises.)

PS

Just scanned the "Going Asynchronous" chapter of Dan Appleman's excellent Advanced Apex Programming – 3rd edition and read:

… native chaining support built into queueable Apex, there is no longer a need to use scheduled Apex in this manner …

but I'm not entirely clear on which of the patterns he describes would fit this case…

PPS

So 2 approaches are proposed in the answers but I still have these questions about them:

  1. "suicide scheduling" but with the advice to also schedule say every hour: what is the best way to ensure that multiple "suicide schedules" don't get created?
  2. my trivial test of enqueueing at the end of a Queueable ran so fast that a significant part of the asynchronous Apex method executions governor limit might be consumed; is anyone using this approach successfully today?

Best Answer

The main downside to scheduling 12 identical events is that if one gets lagged behind for some reason, the next one will run in less than five minutes. This may or may not be desirable. Particularly during maintenance, you may have all 12 jobs trying to execute immediately upon the system coming back from maintenance. Also, if you're running an organization that already has some 90'ish scheduled jobs already (including daily, weekly, and monthly jobs), using 12 slots is undesirable.

I personally prefer using "suicide scheduling" for a granularity of less than an hour, because it uses fewer resources and is still reliable. With suicide scheduling, your job purposefully does something, aborts itself, and schedules itself X minutes in the future with an hourly schedule fallback. This way, if it fails to reschedule because of blown governor limits or an unhandled exception, it'll run in an hour, otherwise it'll run in X minutes, and all you need is a single job.

Here's what it generally looks like:

public class SuicideScheduler implements Schedulable {
    public void execute(SchedulableContext context) {
        System.abortJob(context.getTriggerId());
        System.schedule('SuicideScheduler', '0 '+DateTime.now().addMinutes(5).minute()+' */1 ? * *', this);
        // Do your payload now
    }
}

However, you could also avoid this problem entirely by just scheduling yourself hourly and using a Queuable/Batchable class that the scheduler kicks off:

public class QueuedScheduler implements Schedulable, Queueable {
    public void execute(SchedulableContext context) {
        System.enqueueJob(this);
    }
    public void execute(QueueableContext context) {
        // Do your work here
        // 
        // If you need to chain, then you can...
        System.enqueueJob(this);
    }
}