Scheduler
Contents
Named tasks can be scheduled to asynchronously run in the background in a cluster or a one-node environment.
Scheduled Job
A scheduled job is an object which describes how a named task must be run. It contains information about the type of scheduling, time of execution, description, etc. All job nodes are stored in a separate system.scheduler repository. See how to manipulate it with lib-scheduler API.
Properties
| Name | Type | Description | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
name |
string |
Name of a job, unique for the entire environment |
|||||||||||||||
|
description |
string |
String-format description of scheduled job |
|||||||||||||||
|
descriptor |
string |
Descriptor of the task to be scheduled. Format: |
|||||||||||||||
|
config |
object |
JSON object contains described task parameters |
|||||||||||||||
|
calendar |
object |
Describes when the task should run
|
|||||||||||||||
|
user |
string |
Principal key of the task submitter. Format: |
|||||||||||||||
|
enabled |
boolean |
If |
|||||||||||||||
|
creator |
string |
Principal key of user that created the task |
|||||||||||||||
|
modifier |
string |
Principal key of the last user that modified the task |
|||||||||||||||
|
createdTime |
string |
Time of the task creation |
|||||||||||||||
|
modifiedTime |
string |
Time of the last task modification |
|||||||||||||||
|
lastRun |
string |
Time of the last job run |
|||||||||||||||
|
lastTaskId |
string |
Task id of the last job run |
Calendar
Calendar object describes when and how the task should be run. There are three possible types: one-time, cron and fixed-rate.
The task will be run only once. If the time value is passed at the moment of scheduling, then the task will be run immediately. Value format is ZULU time, documented in ISO 8601.
{type: 'ONE_TIME', value: '2021-01-01T10:30:00.00Z'}
The job remains after it has run, with lastRun recording that it is done, so its name cannot be reused to run it again. XP 8.1.0 Where the name is used for a single occasion only - a publish request keyed by a uuid, say - that record protects nothing and only accumulates; deleteAfterRun makes the job remove itself once its task has been submitted.
{type: 'ONE_TIME', value: '2021-01-01T10:30:00.00Z', deleteAfterRun: true}
Should be used for repeatable tasks. UNIX cron lib format is expected. Also, a timezone must be specified to run the job at a particular time of the day.
{type: 'CRON', value: '* * * * *' // every minute
,timeZone: 'GMT+5:30'}
XP 8.1.0 Should be used for repeatable tasks that belong at an interval rather than at a time of day. The value is an ISO-8601 duration, and the interval is measured from when the previous run started - not from when it finished, and not from the clock, so no timezone applies.
{type: 'FIXED_RATE', value: 'PT5M'} // every five minutes
What a fixed rate promises:
-
The interval is between the starts of two runs, not the gap between them.
-
A run that overruns its interval delays the next one instead of overlapping it, and the delayed run starts once its predecessor finishes.
-
Periods missed while a run overruns are not replayed, so an overrunning run shifts every later run along with it.
-
The interval is not anchored to any wall-clock position, and is not preserved across a restart or a move to another node - the next run may shift by up to one interval.
Use CRON instead where a run has to land at a particular time of day.
System jobs
XP platform provides predefined system jobs, which can be enabled and overridden by user in config file. The config file creates jobs, it does not maintain them: XP 8.1.0 a job added to the file is created within a second, but editing an entry never updates a job that already exists, so remove or change the existing job first.
Deletes unused blobs and binaries from a blobstore.
| Make sure you have a backup of the installation available before doing a vacuum. |
init-job.vacuum.enabled=false
init-job.vacuum.cron=0 5 * * *
init-job.vacuum.descriptor=com.enonic.xp.app.system:vacuum
init-job.vacuum.description=Job to run vacuum
init-job.vacuum.user=system:su
Common vacuum process config can be found in Vacuum config file.
Deletes records from audit log repository.
| Make sure you have a backup of the installation available before running a cleanUp. |
init-job.audit-log-cleanup.enabled=false
init-job.audit-log-cleanup.cron=0 5 * * *
init-job.audit-log-cleanup.descriptor=com.enonic.xp.app.system:audit-log-cleanup
init-job.audit-log-cleanup.description=Job to clean up old audit log history
init-job.audit-log-cleanup.user=system:su
Common cleanup process config can be found in Audit config file.
ageThreshold property must be set to appropriate value, otherwise nothing will be removed. |
Distributable
A scheduled job is submitted once per due occurrence, from one node of the cluster, and the task it submits then runs on any node that has the application providing it - see task for where that can be. Which node submits is a deployment concern, set with acceptScheduling in the scheduler config file; a job behaves the same wherever it is submitted from.
XP 8.1.0 A job does not start a run while its own previous run is still going. What becomes of the run that was due depends on the calendar: a CRON occurrence is skipped, since a cron occurrence is a position in the calendar and a missed one is missed, while a FIXED_RATE run is delayed and starts once its predecessor finishes.
| Not overlapping is best effort, not a guarantee. Two runs of the same job can still overlap when the cluster is partitioned, or when the record of the previous task is no longer available to be checked. A task that must never run concurrently with itself needs a lock of its own. |
| The guarantee is per job, not per task. Several jobs may name the same descriptor, and nothing relates them - they can run at the same time as each other. |
What a scheduled task receives
A scheduled task runs with the config of its job as parameters, exactly as if it had been submitted through the task API.
XP 8.1.0 It also learns which task ran for the job last, through the schedule.lastTaskId attribute of its context. That is useful where each run continues from where the last one reached - fetching the previous run’s result to process only what has changed since. The value is absent on a job’s first run and on a job whose last run left no record.
import {get as getContext} from '/lib/xp/context';
import {get as getTask} from '/lib/xp/task';
export function run(): void {
const lastTaskId = getContext().attributes['schedule.lastTaskId'] as string | undefined;
const previous = lastTaskId ? getTask(lastTaskId) : null;
if (previous) {
log.info('Previous run: %s', previous.state);
}
}
The chain only ever names tasks the scheduler let run, so an id that is there is one whose run actually happened.