Skip to content

Routines

Routines are bilbycast-manager’s automation surface. A routine is a named bundle of actions (start a flow, stop a flow, restart a flow, or activate a Switcher preset) plus zero or more schedules that fire it on a recurring or one-shot cadence.

If the Live Switcher is the director’s manual console, Routines are the programme schedule — sponsor blocks, prime-time switches, weekday news cuts, weekend feeds, and “set up the rig at 6am every weekday” maintenance windows.

Live broadcast plants run on the clock. The same channel that’s on national news at 18:00 is running sponsor blocks at 18:30 and the late-night feed at 22:00. Routines let an admin programme that schedule once, then leave the manager to fire it — every day, every week, with full audit and DST correctness.

Operators can manually fire any routine with one click — useful for emergency takes, dry-runs, and ad-hoc switches outside the scheduled programme.

A routine has one or more actions. Each action is one of:

ActionWhat it does
flow_startStart a flow on a target edge node.
flow_stopStop a flow on a target edge node.
flow_restartRestart a flow on a target edge node.
activate_switcher_presetRun the same logic the Switcher’s Activate button does — including per-node Operate permission checks.

A routine with multiple actions fans them out concurrently. The aggregated outcome is success (all actions ACK’d OK), partial (some failed), or failed (all failed). Partial and failed outcomes raise real-time alarms; success is silent (recorded in activation history but not in the events feed) so a busy schedule doesn’t drown the alarm panel.

The recurrence picker has five preset frequencies:

FrequencyExample summary
Once”Once on 2026-05-30 22:00 — Australia/Sydney”
Daily”Daily at 18:00 — Australia/Sydney”
Weekdays”Weekdays (Mon–Fri) at 18:00 — Australia/Sydney”
Weekly”Mon, Wed, Fri at 18:00 — Australia/Sydney”
Customoperator-supplied 5-field cron expression

Every schedule is evaluated in an IANA timezone — your browser’s timezone by default — so a “Daily at 18:00 in Sydney” rule keeps firing at 18:00 local even after a daylight-saving boundary. Operators never have to write cron unless they want to: the picker compiles the choice down to the right expression and round-trips via a stored human-readable summary.

You can also set a valid-from and valid-until window so a schedule only runs between two dates (Olympic-style limited campaigns, fixed sports seasons, retiring an old promo).

If a director needs to skip a single scheduled fire — say, a sponsor block shouldn’t run during a memorial broadcast — they can click Skip next fire on the schedule row without disabling the schedule entirely. The scheduler advances past the upcoming fire and clears the override automatically. No admin call required; operator-friendly by design.

If the manager is offline when a scheduled fire was due, anything older than 15 minutes past its next_fire_at is not replayed. It’s logged as missed in the activation history and emits a routine_fire_missed warning event. Fires within the 15-minute window do replay on the next tick.

The broadcast rationale: don’t replay sponsor blocks at midnight just because the server was off all afternoon. The 15-minute grace window covers expected ops events (HA failover, deploy window, brief outage) without forcing an operator to manually rebuild the queue.

ScenarioBehaviour
Spring-forward (e.g. Australia/Sydney 2:30 doesn’t exist on the changeover day)A 02:30 daily rule fires once at 03:00 on the changeover day, then back to 02:30 on subsequent days.
Fall-back (the local 02:30 happens twice on the changeover day)A 02:30 daily rule fires once at the first 02:30 occurrence; the second 02:30 wall clock is silently skipped.

Driven by chrono-tz and the cron crate, validated by unit tests on Australia/Sydney boundaries.

In an Active/Active HA pair two manager instances see the same routine_schedules rows. The scheduler uses Postgres pg_try_advisory_xact_lock(<schedule_id>) per due row to claim a fire — the first instance wins, the second backs off cleanly. No leader election, no clock drift to manage, no double-fire risk.

Surfaced on the manager’s Events page under category routine:

EventSeverityWhen
routine_fire_partialwarningSome actions in a fire failed. details.failed_actions[] tells the operator which.
routine_fire_failedcriticalEvery action in a fire failed. Wakes the alarm panel.
routine_fire_missedwarningA fire was older than the 15-minute window and wasn’t replayed. details.lag_seconds.

Success fires don’t emit a real-time event — they’re visible in the activation history but they don’t drown the alarm panel.

  • Creating, editing, deleting routines and schedules requires the Admin role in the owner group.
  • Manually activating a routine requires the Operator role plus per-node Operate permission for every action’s target node.
  • Scheduled fires run as the system actor (user_id = NULL). Permission is verified at routine-creation time, not at fire time, so scheduled programming doesn’t break because the morning operator went on leave.

Routines are first-class tenant-scoped resources — an admin in Acme manages Acme’s routines without seeing Globex’s. Cross-tenant composition is rejected at create time: a routine in Acme cannot reference a switcher preset whose owner group is Globex.

  • Operator walk-through: USER_GUIDE.md (“Routines (scheduled flow automation)”).
  • Architecture, scheduler internals, missed-fire policy: routines.md.
  • API reference: API.md (“Routines (scheduled flow automation)”).