Airwave

Scheduling

How bumpers are materialized into a channel's timeline, the rev-based Bumper Sync reconcile job, and why only structural settings rebuild schedules while music and style are playback-only.

Bumpers aren't decided at play time — they're baked into the schedule. When Airwave materializes a channel's timeline, it weaves interstitial breaks in as their own slots, so the guide and players read them straight from ScheduleItem rows.

How a bumper lands in the timeline

During a schedule build (packages/api/src/services/schedule/timeline.ts), the engine first resolves the channel's break planresolveBumperPlan(globalConfig, channel). If that returns null (bumpers globally off, or the channel's mode is Off) no breaks are woven and the timeline is programs-only. Otherwise an interstitial is inserted before each program, with two rules:

  • Never before the very first slot of the build — so tuning into a mid-stream channel isn't greeted by a break.
  • Each break targets the program that follows it — that upcoming item is the "Up Next" the interstitial card renders.

Each break's length is chosen contextually by breakSeconds from the outgoing→incoming pair (see Interstitials). The resulting slot is a ScheduleItem with:

FieldValue on a bumper
kindBUMPER
ratingKeynull — nothing streams; the client renders the card
bumperKind"interstitial"
targetMediaItemIdthe upcoming program's MediaItem (the "Up Next")

The rev stamp and Bumper Sync

Because breaks are baked in, a settings change has to reach already-built schedules. That's handled by a version stamp:

  • The global BumperConfig has a rev counter. A full schedule build stamps the channel's Channel.bumperRev with the rev it built under (generate.ts).
  • Changing a structural setting increments rev, making every channel built under the old rev stale.

The Bumper Sync job (schedule-bumper-sync) reconciles the stragglers. It runs every 10 minutes in batches of 10 channels (and is kicked immediately when you save a channel's bumper mode, or a structural global change lands). A channel is out of sync when either:

  1. Whether bumpers should be present differs from whether they are — i.e. bumpers were toggled on/off globally or the channel's mode changed; or
  2. Bumpers are present as they should be, but the channel's bumperRev is behind the global rev — which catches any structural settings change (break-length tiers, the short-episode threshold, …).

For each stale channel it does a full generateChannelSchedule, which re-weaves the breaks and re-stamps bumperRev. Batching keeps a lineup-wide change from rebuilding everything at once; the cron picks up the rest on the next passes. Bumper Sync only touches channels that already have a schedule — the initial build for a new channel is Schedule Backfill's job.

Structural vs playback-only

Not every setting rebuilds schedules — the update handler (packages/api/src/routers/bumpers.ts) bumps rev only when a structural field actually changed value:

Structural (rebuilds schedules)Playback-only (no rebuild)
enabled (master switch)Ambient music: musicEnabled, musicVolume, fades
Break lengths + shortEpisodeMinutesInterstitial card style
Deprecated interstitialMusicKey
The track library (upload / toggle / rename / delete)

The reason: only bumper presence and durations are baked into the timeline. Everything else — the ambient bed (DVR-derived client-side), the card's look — is read by the client at play time. So flipping bumper music on or off, or nudging its volume, takes effect on the next break without regenerating a single schedule. Toggling breaks on/off or retuning a break length does rebuild, via the flow above.

The music scan job

Separately, Scan Bumper Music (bumper-music-scan) is a manual job that reconciles the music library with its volume — indexing files dropped straight into the folder, flagging tracks whose file went missing, and clearing the flag on any that reappear. It has nothing to do with schedules; run it after adding files to the volume by hand.


See also: The schedule · Background jobs · Configuration · Interstitials

On this page