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.
There are three important components in this architecture.
-
Salesforce Scheduler: This is the main Salesforce engine that keeps track of all scheduled jobs and runs the jobs at the appropriate interval.
-
Schedulable Classes: These are your Apex Classes which implements
Schedulable
Salesforce Interface. -
Job Classes: These are the work-horse classes which implement your job function.
Here is how the same setup looks with Scheduleright.
With Scheduleright, there are a couple of things changing. Mainly,
-
You do not write Apex Classes which implements
Schedulable
interfaces. Instead, SC]Scheduleright will schedule its own classes with Salesforce. This process is calledSetting up Schedules
. -
You manage the jobs from Scheduleright UI interface
-
There are no apparent changes to your
Queueable
orBatchable
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
-
Obtain the package url [We are working on having this package published in Appexchange. Meanwhile, contact us for package url]
-
Enter url into the browser and follow the installation process as described here. Typically this package is installed for
Admins Only
- Let installation run through its course and you should get this success page after few minutes.
- Since Schduleforce is a managed package (with namespace
dsr
), it cannot directly access the classes defined in your org (unless they areglobal
).
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));
}
}
- Now access the Scheduleright app from Lightning app
- Installation should have created a first job, which is used to cleanup the runs after configured number of days (defaults to 180)
- Click on the
Edit Global Settings
to access the Scheduler Global Settings and specify the valueSchedulerInstanceCreatorImpl
for Instance creator setting.
- 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
By default it shows the Schedules are not setup.
Click on Setup Schedules
It should show confirmation page with status indicating Schdeules have been setup. Now Scheduleright is ready to schedule jobs.
- Now it is time to setup first job. You would need to use the job class which is appropriate for your org.
- If you wait for a while, the status should be shown when you access the Job page.
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
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();
}
-
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. -
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.