Scheduleright Docs

Overview

Scheduleright is an enterprise-grade Job Scheduler for Salesforce. It aims to provides many capabilities that teams come to expect of typical Job Scheduler.

It is 100% native Salesforce manage package and doesn’t connect to any external services to function.

Features

Here are the top features of Scheduleright.

  • Minute level Scheduling vs Standard Salesforce’s hour level
  • Comes with many commonly used schedules
  • Supports Job Parameters that can be managed in UI
  • No need to create Schedulable classes
  • Abort Jobs if they are not completed after certain interval
  • Sequence the Job Runs so new job is scheduled till previous runs are completed
  • Set an arbitrary delay on a job
  • Inactivate Jobs without deleting the configuration
  • View the Run History
  • Powerful Notifications
  • Parent-Child Jobs
  • Cross Job Dependencies
  • Pre-defined Jobs for everyday tasks
  • Visualize using Standard Reports
  • Support for different Timezones
  • Automatically log apex errors
  • Capture the Run Log

Architecture

This section gives a very high-level design overview of the Scheduleright. Having this understanding can help you visualize how this package works and interacts with Salesforce.

Typical Salesforce scheduling is as follows. Sfdc Scheduler

There are three important components in this architecture.

  1. Salesforce Scheduler: This is the main Salesforce engine that keeps track of all scheduled jobs and runs the jobs at the appropriate interval.

  2. Schedulable Classes: These are your Apex Classes which implements Schedulable Salesforce Interface.

  3. Job Classes: These are the work-horse classes which implement your job function.

Here is how the same setup looks with Scheduleright. Sfdc Scheduler

With Scheduleright, there are a couple of things changing. Mainly,

  1. You do not write Apex Classes which implements Schedulable interfaces. Instead, SC]Scheduleright will schedule its own classes with Salesforce. This process is called Setting up Schedules.

  2. You manage the jobs from Scheduleright UI interface

  3. There are no apparent changes to your Queueable or Batchable jobs [You may have to make changes to your jobs if you want to take advantages of Job Parameters. We will go over this later.]

Objects

Scheduleright creates three objects as below.

Object Description
Scheduler_Job__c This object is used to save all Scheduled Jobs.
Scheduler_Job_Run__c This object is used to save the Scheduled Job Runs
Scheduler_Job_Dependency__c This object is used to define the cross job dependencies

Installation

  1. Obtain the package url [We are working on having this package published in Appexchange. Meanwhile, contact us for package url]

  2. Enter url into the browser and follow the installation process as described here. Typically this package is installed for Admins Only

Image

  1. Let installation run through its course and you should get this success page after few minutes.

Image

  1. Since Schduleforce is a managed package (with namespace dsr), it cannot directly access the classes defined in your org (unless they are global).

To allows Scheduleright to access your classes, we will need to create this simple class which instatiates the classes in your org. Create these two classes (one main and one test) in your org and save them. If you are installating this in production org, at this time you will need to deploy these two files from one of your sandboxes.

/**
 * Global implementation of Scheduleright interface, used to create instances of classes
 * as and when required it to be scheudled.
 */
global class SchedulerInstanceCreatorImpl implements dsr.SchedulerInstanceCreator {
    global Object createInstance(dsr.SchedulerInstanceCreatorRequest req) {
        return Type.forName(req.className).newInstance();
    }
}
@IsTest
public class SchedulerInstanceCreatorImplTest {    
    testmethod public static void test_createInstance() {
        dsr.SchedulerInstanceCreatorRequest req = new dsr.SchedulerInstanceCreatorRequest();
        req.className = 'SchedulerInstanceCreatorImpl';
        System.assertNotEquals(null, new SchedulerInstanceCreatorImpl().createInstance(req));
   	}
}
  1. Now access the Scheduleright app from Lightning app

Image

  1. Installation should have created a first job, which is used to cleanup the runs after configured number of days (defaults to 180)

Image

  1. Click on the Edit Global Settings to access the Scheduler Global Settings and specify the value SchedulerInstanceCreatorImpl for Instance creator setting.

Image

Image

  1. We need to enable the schedules. This is the step where Scheduleright hooks up with Salesforce by creating 60 Scheduled jobs, to run every minute. Note that if your org has already uses 40 or more jobs, then not all schedules hookups will be successful. To facilitate the install, delete some of the Scheduled Apex jobs, and follow this step again. With Scheduleright installed, you do not need to schedule any more classes directly.

Click on Manage Scheduler from menu

Image

By default it shows the Schedules are not setup. Click on Setup Schedules

Image

It should show confirmation page with status indicating Schdeules have been setup. Now Scheduleright is ready to schedule jobs.

Image

  1. Now it is time to setup first job. You would need to use the job class which is appropriate for your org.

Image

  1. If you wait for a while, the status should be shown when you access the Job page.

Image

Accessing the UI

Scheduleright creates an app named Scheduleright. Access the lightning view and select the app. This app has only one tab Scheduler Jobs, which allows you to manage the jobs.

Note: Scheduleright is designed with Lightning experience in mind. While many functions will fine in Classic, some of the actions may not be available at this time.

Managing Jobs

Managing Jobs is as simple as creating/editing/delete records from Scheduler_Job__c object. Following table documents the fields, you can edit as part of the Job. All other fields which are not listed below table are considered internal and should not be edited.

Field Type Required Default Description
Job Name String Yes Job name. Can be up to 80 characters
Class String Yes The Apex Class associated with this job. Class must implement either Queueable or Batchable interface
Frequency Picklist Yes The frequency with this Jobs needs to be scheduled. You can choose of the pre-defined intervals or specify your own by choosing Cron . If would like to run this job not on a fixed interval but ad-hoc, choose On Demand
Cron Pattern String Maybe If you choose Cron as Frequency, specify the cron pattern string. See the Cron Pattern section for more information
Active Checkbox If checked activates the Job and makes it available for Scheduling. If unchecked, then job will not be scheduled.
Description Textarea Any description that describes the Job, what it does and when it is supposed to run.
Parent Job Reference If this Job is a child job, select its parent job. If you select a parent job, the Frequency must be set to Depends on Parent . See Parent/Child Jobs for more information
Timezone Picklist Specifies the Timezone that should be used to calculate the time eligibility. This overrides the default timezone set as part of Global Scheduler Settings. If you want to set to default again, choose Default
Wait on Pending Runs Checkbox If checked, Scheduler will wait for all previous runs of this job to be finished before starting a new run. Select this check box if you want to avoid concurrent executions of the same job. If you are okay with concurrent executions, then leave this option unchecked.
Batch Size Integer 100 This is applicable only for Batchable jobs. Indicates the batch scope with which the batch job will be executed. This indicates the number of records that Salesforce passes in to execute method. Defaults to 100 .
Abort After Minutes Integer Number of minutes after which, previous job executions will be aborted, if they are not finished yet. Use this option, if you notice any of your Jobs are getting stuck in Processing status for a long time after they supposed to be completed. Use with caution
Order of Execution Integer If you have two jobs which might mature at the same time, this would help which jobs are picked up first. Any valid integer would do. Lower the value, higher the priority.
Delay Until Datetime Specifies the datetime until this job should not be scheduled. Many customers use this to add delay to execute On Demand jobs.
Notification Types Multi Picklist Indicates the types of notifications that should be used to notify jobs execution failures. You can choose zero or more types. If no types are selected, then no notification will be sent out.
Notification Emails Textarea If you have selected Emails as one of the Notification types, you can specify the list of users to which that notification should be sent out. This is in addition to Default Notification Emails that can be set at Scheduler Global Settings.
Slack Webhook Url Url If you have selected Slack as one of the Notification types, then specify the Slack url to which the notification should be sent. Note that you can specify default Slack webhook url in Global Scheduler Settings.

Activating/Inactivating Jobs

The Active__c field on Scheduler_Job__c indicates if that Job is active or not. If a Job has been inactivated, then Scheduler will not schedule that job. When it is inactivate, the Scheduling Status should show as as scheduling status inactive

You can mass activate/inactivate the Jobs via Scheduler Job listview or use Apex script.

Run History

Each time Scheduler schedules a job, we create a record in Scheduler Job Run object. That object also has corresponding AsyncApexJob Id. The scheduler will track its status and update every time it runs (in normal conditions it is every minute).

You can force update the status using Refresh Run Status action in Job details screen.

Pre-defined Schedules

The scheduler has many pre-defined schedules. These are added based on the commonly used scheduling intervals by many customers. If you have new schedules that might be useful for other customers, let us know and we will try to incorporate it. Note that if none of these meets your needs, you can always specify custom cron.

Schedule
Every Minute
Every 5 Minutes
Every 10 Minutes
Every 15 Minutes
Every 20 Minutes
Every 30 Minutes
Every Hour
Every 15 Past Hour
Every 30 Past Hour
Every 45 Past Hour
Every 2 Hours
Every 3 Hours
Every 4 Hours
Every 6 Hours
Every 8 Hours
Every 12 Hours
Every Day
Every Sunday Night
Every Monday Night
Every Tuesday Night
Every Wednesday Night
Every Thursday Night
Every Friday Night
Every Saturday Night
Every First Day of Month
Every 15th Day of Month
Every Last Day of Month
Every First Weekday of Month
Every Last Weekday of Month
Every First Day of Quarter
Every Last Day of Quarter
Every First Weekday of Quarter
Every Last Weekday of Quarter
Every First Day of Year
Every Last Day of Year
Every First Weekday of Year
Every Last Weekday of Year
Every First Monday of Year
Every Last Friday of Year

Cron Pattern

Scheduler supports full cron pattern as Salesforce (as documented here) with few important differences as outlined below.

  • Seconds part must always be zero
  • You can use special chars (- , * /) for minute and hour parts

Capability to support special chars in minute and hours allows you to setup Jobs which much more granular level than what you can in Salesforce.

Schedulable Apex Classes

Schedulable apex classes are type of classes that Salesforce allows registering scheduled jobs. Typically, you would implement these classes for each scheduled job. While some programming can be done in these classes directly, they are not recommended and it should be used only to kick off other background jobs. So creating/testing this type of classes becomes an additional burden for customers before they can be used to Schedule jobs in production.

Scheduleright removes the necessity to create such classes. You will need to implement only background jobs (Queueable or Batchable) and use them directly to schedule with Salesforce.

One added benefit of not having to create Schedulable classes is, no more dreaded This Apex class has batch or future jobs pending or in progress message when you edit your Apex classes in Sandboxes.

Aborting Jobs

Some times background jobs get stuck in kind of Zombi state and not progress away from Queued or Processing status. Few such stuck jobs can completely block other batch jobs from being executed (since Salesforce allows only 5 Batch jobs to be in those states).

You can get control of such situation by specifying the Abort after Minutes value. If that value is >= 1, then Scheduler will automatically abort the job if that is still not completed that many minutes after starting the job. The job status will be marked as Aborted.

Parent/Child Jobs

Parent/Child jobs allow you to model parent/child dependencies between jobs. In that case, all child jobs cannot be specified with a particular frequency and are tired to its parent job’s frequency. Child Job’s frequency will be set as Depends on Parent.

To setup a parent/child job, goto child job and select its parent in Parent Job field and save. Frequency will automatically be set to Depends on Parent. From that point on, when parent job is matured, child job will be executed after completion of parent job execution.

You can setup multi-level parent-child jobs. Follow the same steps that goto child job and select its parent.

You must be really careful to ensure that there is no circular dependency (Job A -> Job B -> Job A). If you setup like this, the job will never be scheduled.

You can view the Job Tree by selecting View Job Tree when you are in any of those parent/child jobs.

Wait on Previous Runs

If you have a batch job that is already running, and the time comes to schedule next one based on the time interval, Salesforce will go ahead and start this job. This behavior may be fine. But sometimes it is not if your job is not designed to be run in parallel.

Scheduleright allows you to control if you want all the run of a job to be run in serial mode via Wait for Previous Runs field. Note that if there are already some runs underway before you enable this flag, those are not impacted by this flag. They will continue to run in parallel but it will ensure from next scheduling on.

What if you have a job, that depends on other jobs (For ex., Sync Account depends on Normalize Accounts)? Scheduleright supports that too. Check out next section.

Cross Job Dependency

If you a job which is not a parent/child but still want to ensure that they are not run in parallel, you can use Cross Job dependencies. Goto Job details in the UI and create Scheduler Job Dependencies records. A job can depend on any number of other jobs. If any of those Jobs have non-finished runs, then that job will not be scheduled till those are completed.

Be careful about circular-dependencies. If you define a circular dependency, then Jobs may not be scheduled at all.

Timezone Support

Timezone is used any time we need to calculate if a Job is required run at a particular time. This is relavent for Jobs which have Frequency other than On Demand or Depends on Cron. Specifying the Timezone would make Scheduler mature the time-frequency according to that timezone.

For ex., the frequency of Everyday and Timezone as America/Los_Angeles would make Job run everyday night midnight according to Pacific timezone.

Different Jobs can be specified with different timezones. If you don’t care about Job level customizability and okay with specifying one for Scheduler Global level, specify that timezone in Scheduler Global Settings.

Job Parameters

One of the painful experience of dealing with Salesforce Scheduler needs to write Schedulable interface for each of the changes that we need to make, test them and deploy to production even to change one simple thing inside background jobs.

Job Parameters alleviate this issues by providing a type checked, and safe mechanism to specify parameters that can be customized at the individual job level. So even if you are using the same class for multiple jobs, each job instance be configured with different parameters. This allows you to adopt per business needs almost immediately.

Implementation

To take advantage of Job Parameters, your background jobs need to implement SchedulerJob interface. The SchedulerJob interface is shown below. To see the details of associated classes check out Api Spec

global interface SchedulerJob {
    void setJobInfo(SchedulerJobInfo info);
    List<SchedulerJobParamInfo> getParamInfos();
}
  1. List out all the parameters that your job supports and return that list via getParamInfo method call. That method will be called by the scheduler to understand what parameters your job needs and allows to edit those in the UI.

  2. Then scheduler will call setJobInfo with job info object which allows you to get those parameters, log statements and get additional details about the job.

See the sample implementation of this concept in Api Spec

Set Values

Once your job implements framework classes, it is now ready to set parameters from UI. Choose Edit Job Parameters action in Job page to set the values for these parameters.

Scheduler Global Settings

The scheduler has many settings that are applicable globally for all jobs. Some of these can be specified only at the Global level and some of these can be overridden at the Job level.

Settings are stored in a custom settings Settings__c created as part of Libforce managed package.

You can view/update these settings by selecting Scheduler Global Settings action in any of Job’s detail page.

Setting Type Required Default Description
Default Timezone Picklist Default timezone that must be used for all Jobs. This setting can be overridden at the job level.
Default Notification Types List of Strings List of default notification types that are applicable for all jobs. This setting can be overridden at the job level.
Default Notification Emails List of Strings This is the default list of emails that need to be notified. This setting can be overridden at the job level.
Always Notification Emails List of Strings This is the list of emails that will always be notified for all jobs
Default Slack Webhook Url Url Default Slack Webhook Url. This URL can be overridden at the Job level.
Admin Emails Url This is a list of admins that will be notified if there are any issues with scheduling itself. These emails should be pretty limited.
Max Queueable Schedules Integer 50 Maximum of Queueable jobs Scheduler can schedule in one transaction (that is every minute). This should be maximum that is allowed by Salesforce. Defaults to 50.
Max Batchable Holdings Integer 100 Maximum of Batch jobs are allowed to be in Holding state. After this specified count, Scheduler will stop scheduling any more batch jobs in that transaction and will be pushed to next one. This should be Salesforce maximum, currently is 100.
Message Builder Apex Class 100 If you want to customize the message that is sent in Emails, Slack message or another channel, provide an Apex Class that implements dsr.SchedulerMessageBuilder interface and customize the content as you please
Notification Title Prefix String When you receive a Job failure notification, you would want to know if this is from Sandbox or production. This setting allows you to set a prefix that will be added to email subject, slack title etc., For ex., you can specify [PRD] for production, [STG] for stage etc.,

Job Run Log

When you start a background job, and something happens, unless you have setup Debug Logs in Salesforce, what happens inside is a black box. Run Log allows you to log some meaningful logging statements as part of your job execution and have those logs stored conveniently at Job Run. Later you can view the run log from Run Details screen. You can generate up to 1 MB of log at this time.

To be able to log, your Queueable or Batchable jobs needs to extend from SchedulerJobQueueable or SchedulerJobBatchable respectively. If your jobs already extends from other classes you can implement SchedulerJob interface.

Once you extend/implement, you will be passed an instance of type SchedulerLogging that has method to add debug statements and save those statements at the end of it.

Pre-defined Jobs

There are some jobs that are not specific to any customer’s business process. Scheduleright intends to provide many such jobs to ease customer’s problems.

Here are some of those jobs. If you have a job requirement in mind, and can be used by other customers, let us know. We will work with you to understand more and add it as one of the supported jobs by Scheduleright.

Mass Update

SchedulerMassUpdateJob allows you to update any Object (either standard or custom) and any number of fields in that object. Fields can be updated to a fixed value or map to another field from the same object or from its parent object.

Mass Update uses following Job Parameters.

Parameter Type Required Default Description
Query String Yes The query the Mass Update job needs to execute to identify set of records it needs to update. This query must also select all fields referred in the update spec. For ex., select id, name, phone, billingstreet, shippingstreet from account where billingstate = 'CA'
Update Spec Json Yes This is a json string specifying how to process the update request.

To use this pre-defined job, create a new Job with apex class SchedulerMassUpdateJob and set the parameters.

Mass Delete

SchedulerMassDeleteJob allows you to delete records (millions of them if you would like) from any deletable objects (including standard and custom objects). Optionally, it can also hard delete the records so that deleted records will not clog up the recycle bin purging important records.

It supports following job parameters.

Parameter Type Required Default Description
Query String Yes Soql query to select records that need to be deleted
Hard Delete Boolean false Flag indicating if job should hard delete the records.

To use this pre-defined job, create a new Job with apex class SchedulerMassDeleteJob and set the parameters.

Mass Purge

SchedulerMassPurgeJob allows you to purge records from recycle bin conditionally.

It supports following job parameters.

Parameter Type Required Default Description
Query String Yes Soql query to select records that need to be purged. Make sure your soql query has predicate IsDeleted=true

To use this pre-defined job, create a new Job with apex class SchedulerMassPurgeJob and set the parameters.