Skip to main content
Skip table of contents

Understanding ROAD Schedules

This document is intended for a deeper understanding of ROAD schedules. It is recommended to read first the basic documentation on ROAD schedules data in Schedule Data.


When a ROAD schedule hits, this means it leads into an occurrence at a time. Then a job is being created timely before it will start (usually some minutes before) and a Worker is started being prepared and ready to start exactly at the requested time. The duration or finishing the job is either specified inside the schedule or by the template. Anyway the time frame of a schedule is only considered for the start time, but not for its processing time (so several overlapping jobs are not prevented by the scheduler).

A ROAD schedule contains a TimePlan, which defines when the schedule will lead into occurrences of a job being created from the referred job template. This can lead into one ore more occurrences (or none if defined respectively), depending on the TimePlan definition.

How are Schedules Processed by the ROAD Service?

When the ROAD Service's ScheduleRunner component is triggered, it does a database query for all schedules, which are related to its specific host name. For all those the next occurrence (= hit) is calculated. If this hit is now pending, it will create a job from the schedule's specification and create a Worker process in prepared (= waiting) state. The job gets a defined start and stop time from the occurrence's start and duration. The Worker then cares for the exact timing and processing the job.

Note a standby schedule is always pending, so a job is being created if there is not already one running.

The ScheduleRunner inside the ROAD Service runs periodically (time is configured by ScheduleRunnerPeriod parameter, see Configuration Parameters of ROAD Service) and considers all hits after the last check until the period time into future. When a schedule is created, updated or deleted by a client, it depends on the REST parameter ResetOccurrences if the ScheduleRunner gets immediately active to update this schedule - so if a currently running job is finished and if a new job is pending.

When the ROAD Service is being started, it remembers the last time schedules were checked and considers all pending occurrences since then. Depending on the schedule's field ResumeInterruptedJob missed occurrences will be resumed if the planned end is not already past (which applies always if the occurrence has "indefinite" duration). Mind that stopping the ROAD Service leads into stopping all Workers and their jobs, also if caused by a schedule.

In Which Way is a Scheduled Job Created?

The created job's specification is taken either from the template being referred by the schedule or from the JobDescription being contained in the schedule. The job's name is set automatically to reflect its origin by this schedule.

The used JobDescription must contain one transition, which must have a PipeSpec. Further transitions are not used for scheduling. A trigger which might be defined inside the JobDescription is ignored. Instead a time trigger is generated to start the job at the time of occurrence.

In case the job contains an ExternalControlConfig or is defined as standby, the first trigger goes to wait by default or to another state, if defined in the JobDescription.

If the applied occurrence has a duration, a stop trigger is created in a second transition.

How is a Schedule’s TimePlan being interpreted?

Imagine the TimePlan as a mechanism producing a list of (potential) occurrences (= hits). Each hit being in inside a given time frame (usually starting with now and ending some time in future) is a point in time to start a job being created from the associated job template. The Recurrences are a list to allow combining different recurrence patterns for one job template (e.g. once every 1. of month + every Monday or on several specific days).

How is a Recurrence calculated?

The calculation of the first hit refers to the Start date+time. The date is the starting point for resolving a recurrence pattern. The time is applied to all occurrences which hit on different days.

The first or next possible match of the Pattern at or after the Start depends on Pattern.Cycle and Pattern.Step. If Weekdays are set, the possible match is restricted to these. For Yearly it is possible to set a weekday definition (e.g. for the second Tuesday in July), even if this seems quite exotic.

The TimeOffset is added to a hit after resolving its pattern. It's quite rarely used, but useful for some special situations (like hitting the day after the last Sunday in month, ...). (question)

After the first match, subsequent hits are calculated following the definition until the FrameCondition or the limit used for a pending query is reached.

If there a more than one Recurrences defined, they are evaluated independently. Each one can define additional occurrences. Possible doubled occurrences are filtered away after evaluating, but possibly overlapping of jobs is not regarded.


The optional FrameCondition can restrict all occurrences to either a time frame or a maximum amount of occurrences. As it comes after all other recurrence definitions, it is omitted from the following descriptions.

  • The option field FirstStart can define a date+time which restricts the first hit.
  • The option field LastStart can define a date+time which restricts the last hit.
  • The option field NumOccurrences can restrict the count of hits. - (warning) This field is not yet implemented


Recurrences are a list of definitions when to run a job. At least one recurrence must be provided, otherwise it won't occur.

All recurrences lead into independent occurrences, so a schedule can be specified to run a job at several specific dates or at some dates and additionally once a month.


Each recurrence refers to a Start. It consists of a date and time. The date is the starting point to all recurrence patterns. The time is kept for all occurrences.


The mandatory Pattern defines how to repeat the scheduled job: once, daily, weekly, monthly or yearly. Additionally a Step cycle can be defined to do it 2-weekly or every second month, etc.

Some detailed facts:

  • The Pattern.Step counting always starts with the time period defined by the pattern type, so
    • Daily: Counting begins with start day
    • Weekly: Counting begins with begin of starting day’s week
    • Monthly: Counting begins with 1st of starting day’s month
    • Yearly: Counting begins with 1st January of starting day’s year
  • The Pattern.Step always starts with the period the Start is in. This applies also if no match occurs inside this first period. This means a starting date after the possible match in the period will lead into the next match to occur later than you could expect. (Example: 2-weekly on Tuesday finds the first match directly in the week of start only if the start is on Monday or Tuesday, but not if start is on Wednesday; in that case the first match will occur not in the next, but in the second next week.)
  • For weekly recurrences it is recommended to set the starting date on the beginning of that period, so there’s no confusion about what will happen. A sophisticated UI should consider this.
  • The yearly cycle refers to the Start date. If Weekdays specifications are added, the next weekday after this date in the respective year matches. If an OffsetInMonth is specified additionally, this is considered for the month the respective date is in.


In addition to the pattern a list of weekdays can be provided to restrict occurrences.

If no weekday definition exists, the job will occur at the first start and all subsequent dates according to the Cycle and Step definition.

For each weekday an OffsetInMonth definition can be provided telling the scheduler to run a job not every week on that weekday, but on the 1st, 2nd, etc. occurrence of that weekday in the month. A negative value means to run on the last, second last, etc. occurrence. Zero means to consider each occurrence. OffsetInMonth must be in range of -4 to 4.

Some detailed facts:

  • Weekdays are supported for all patterns except Daily
  • OffsetInMonth is supported for all patterns except Monthly (and Daily)
  • If an OffsetInMonth is specified for a yearly pattern, this is considered for the month the Start date is in.

Ending the Job

The end time of a job being created from a schedule is result of the (planned) start time and the specified duration. In case the job was started too late (e.g. because the Service was not running), the field DurationIsDecisive defines if to keep the duration or the planned end time. In case no duration is specified, the job will run until stopped by itself (e.g. playout file comes to its end) or by another event.

As the schedule takes full control over the timing, only the first transition from the JobDescription is taken and its trigger is set by the scheduler (except for externally controllable jobs, see above).

Prematurely Ending and Possible Resuming of the Job

When the ROAD Service shuts down, all Workers on the same host will finish processing their job. The finish trigger in their job histories will then show this as the reason.

Scheduled jobs, can be resumed after that under several conditions:

  • Resuming can only occur when the ROAD Service is starting.
  • The job's end time must not be exceeded at this time and there must be at least some time left (configurable by parameter "ScheduleRunnerMinFreeTime").
  • The schedule must have the field ResumeInterruptedJob set with true.
  • Note that only the last possible occurrence of the schedule before the time of restarting the ROAD Service is considered.

When resuming is done a new job is generated from the schedule and the initial trigger will show the reason.

Specifying the Scheduled Jobs

When the schedule hits, the scheduler in the ROAD Service will create a job to be processed. This job's data can either be specified by providing a TemplateId or by providing a JobDescription in the schedule.

By Referring a Template

By specifying the field TemplateId, the job will be created as a copy of the Job part of the referred template:

  • This template's Job data must contain exactly one transition.
  • This one transition must contain the JobDescription (see Job Description Data).
  • A trigger is not required as the triggering is managed by the scheduler. An eventually existing trigger is being removed.
  • The duration of a scheduled job is not defined by a duration trigger in the job template, but by the Duration field of the Recurrence.

By Providing a JobDescription

By specifying the field JobDescription, the job will be created with a name generated from the schedule's name. The JobDescription (see Job Description Data) is used as specified. Triggering will automatically be inserted by the scheduler.

Some More Explanations

  • Only schedules with the matching WorkerHost name are considered. If this field is missing, no ROAD host will be responsible, so this schedule is inactive.
  • The first possible hit is always Start + TimeOffset, where TimeOffset may be negative
  • Patterns generally control the hit of dates. The times are controlled only by Start + TimeOffset.
  • The Once pattern usually is used for one specific date+time, which can be defined by Start. Anyway it’s possible to define “once at the second Sunday of October after Start”. Pattern.Step makes no sense and will be ignored for Once patterns.
  • The time of occurrence is always the specified time plus the defined TimeOffset (which may be negative)
  • A 24/7 is recommended to be managed by a schedule (otherwise it's not stable to restart after it stopped by a reason). This schedule should be defined with duration of exactly 24 hours and daily repeat pattern. Under this condition, the scheduler adjusts the day length to 23 or 25 hours when daylight saving changes require this.
  • Standby schedules with an OutputSwitch definition will be applied with the IntervalOnOutputGraphs option, which leads into creation of output entries of the defined length, regardless of possible pausing while running.
  • Changing an existing schedule (via REST PUT command)
    • overwrites the former schedule,
    • affects future occurrences, therefore pending jobs will be created when needed following the respective rules,
    • does not affect prepared or running jobs (because of this reason jobs should be created as late as possible).
    • Deleting a schedule accordingly affects only future occurrences and leaves already existing jobs.

24/7 Schedules

Jobs which should run all the time (mostly for steady recordings) should be implemented by a 24/7 schedule. By this the ROAD backend cares for running the job, even after it was interrupted.

This is recommended to be configured by

  • Start time: Any time of the day, but preferred a time when a short interrupt is acceptable. If your timezone does daylight saving (DST), avoid the time range of 2:00 to 3:00 as then a DST switch will occur once in spring and once in autumn.
  • Duration 24 hours
  • Repeat by daily pattern

This means such jobs will run for 24 hours, being recurrent every day. This guarantees the job is periodically restarted at a foreseeable time. At this time the recording job is being stopped and new job is started, which can lead into a gap or overlap. The duration of this gap or overlap depends on deviation of timing of the audio source and the host machine's system clock. This is evident especially for streaming sources. In our experience the gap or overlap is mostly less than a second, but maximal some seconds after a running time of 24 hours.

Only by using this pattern a special condition is treated for daylight saving time switches. When they occur, the duration is automatically adjusted to 23 hours in spring and 25 hours in autumn, so the deviating day duration is considered.

Only if the option "Resume interrupted jobs" is set, interrupted jobs will be restarted with next chance. Otherwise only the next day's occurrence will be started after an interrupt.

Standby Schedules

Standby schedules are intended for jobs, which must be ready for immediate start, esp. for external control events (e.g. Ember+, GPIO, Easy REST commands).

  • A Schedule with Standby flag set to true is intended to run always.
  • It will start in Waiting state unless another start trigger is defined in the schedule's first transition.
  • In case it would contain a TimePlan, this will be ignored completely.
  • It is recommended not to finish standby jobs, but using Pause or Pause+OutputSwitch when they should not be in running state.
  • In case a job caused by a standby schedule stops (so the Worker ends), it will be restarted the next time when the ScheduleRunner does it cycle.

Notes on Time Zones and Date+Time Values

ROAD scheduling can be used without caring for time zones, which means all times are treated as local time on the Service host. This works out as long as all ROAD Service hosts and all clients can be considered to have the same local system time zone. If you are using such setup, the following paragraph is not relevant for you.

Almost all time values are stored and passed via the API are related to the time zone specified for a specific schedule. This applies to the FrameCondition and StartTime fields of schedules' TimePlan and the NextOccurrence field returned from a schedules query. This does not apply to the PendingTime field returned by a pending query, because the pending query is intended for usage for a calendar or timeline view or to get a list of upcoming occurrences. In all these use cases it is more useful to receive all times in a common time zone instead of their individual ones.

Why Do We Need Time Zones in ROAD Schedules?

Due to two majors reasons we need to specify a time zone for each schedule's times:

  • The definition of weekdays in a schedule pattern must relate them to a time zone, because a UTC weekday would begin at Greenwich time and not at the weekday from local time's perspective.
  • Specifying a recurrence of a schedule must relate to a time definition valid at the location where e.g. a show is broadcasted. A recurring show will occur e.g. each day at 8:00. When the UTC offset changes at this location due to the DST, this must be reflected in the schedule's occurrence time.
  • Independent from the target time zone a ROAD cluster can consist of several hosts, which even might be located in different time zones.

This means each schedule must specify the time zone its times relate to. (The whole schedule with all its recurrences must be in this time zone as the FrameCondition must relate to it, too.)


Several recurrences of one schedule should never overlap. That may lead into unexpected results as the ROAD scheduler assumes their start and end times come consecutively.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.