[SalesForce] scheduling a batch class to run every 15 min in managed package

I am trying to schedule a batch class to run every 2 min. What I tried so far is :

global class schlerclass implements Schedulable{

   global void execute(SchedulableContext sc) {


        // Re-schedule 
        System.debug('Enter Scheduler class');
        DateTime now  = DateTime.now();
        DateTime nextRunTime = now.addMinutes(2);
        String cronString = '' + nextRunTime.second() + ' ' + nextRunTime.minute() + ' ' + 
            nextRunTime.hour() + ' ' + nextRunTime.day() + ' ' + 
            nextRunTime.month() + ' ? ' + nextRunTime.year(); 
        System.schedule('SchdJob', cronString, new schlerclass());
        // 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
        AbatchClass b = new AbatchClass(); 
        database.executebatch(b);
        system.debug('done scheduling');



   }

}

I try to run this using execute anonymous code:

AbatchClass b = new AbatchClass (); 
String sch = '0 0 11 27 12 ?';
system.schedule('Start Ord Replacement', sch, new schlerclass ());

As I am creating this code as part of managed package and make it available to install , I am wondering how would the user downloading the package should invoke the AbatchClass to run from execute anonymous? Is this something that should be done after installing the package? Can this be trigger from somewhere.

Also, please comment on the approach I followed to schedule a batch job every 2 minutes. Is this a good approach or is there anything better ? Thanks

Best Answer

If part of a managed package I would provide a UI for them to schedule, cancel, etc. I would also make the scheduled and batch class public and not global so the user could not schedule it outside of the ui.

How complicated the UI is is up to you. This is an example UI to illustrate what I mean:

enter image description here

by storing the job Id you can provide for the ability to cancel.

When initially running you would simply use system.scheduleBatch with the minutes being 1 and the batch will run in 1 minutes, then the finish method handle the rescheduling.

As for scheduling every 15 minutes, you can do that in the finish method using system.scheduleBatch and use 15 as the minutes criteria. Essentially the first run kicks off the process. Since you will need the job Id to cancel, you will need to manage that Id as well and update it when you schedule the next batch.

It all depends on how much control you want to have over the process......

To do it using a CRON expression you would need 4 expressions and schedules to do it every 15 minutes..

UPDATE

All of the above is nice but what if you just want a simple answer.

I have done the following:

  1. Allow customer to schedule batch using UI
  2. In the Scheduler Class in the execute I abort the job
  3. In the finish method of the batch class I use system.scheduleBatch to run in 15 minutes

End result, customer use UI to initially schedule batch, schedule aborts itself after first run, batch takes over and schedules every 15 minutes

Schedule Class

global class ExampleScheduler implements Schedulable{ 


   global void execute(SchedulableContext sc) {
        ExampleBatch batch = New ExampleBatch();
           database.executeBatch(batch);

        //Cancel schedule
        CronTrigger ct =
            [SELECT Id,
            CronExpression
            FROM CronTrigger
            WHERE Id = :SC.getTriggerId()];

            System.abortJob(SC.getTriggerId());



   }

}

Batch Class

global class ExampleBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {

        String query = 'Select ID From Account';

        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope) {

        //Do Stuff

    }

    global void finish(Database.BatchableContext BC) {
       if(!test.isRunningTest()) system.scheduleBatch(New ExampleBatch(),'Run again in 15',15); 
    }


}