Deferred Layer Booking with Start After
Automatic license-shortage backoff and operator-scheduled layer starts
August 7, 2026
Layers can now carry a start-after time: a timestamp meaning “do not book frames of this layer before this time.” Two writers use it:
- Automatic backoff. When a frame reports an operator-configured exit status — such as the license shortage that RQD’s log-based exit-status rules can detect — Cuebot pushes the whole layer’s start-after time a few minutes into the future instead of letting the frames retry immediately or die. Frames retry indefinitely without ever consuming a retry.
- Operators and tools, via a new
SetStartAfterRPC, a CueGUI Set Start After… right-click action, and pycue’sLayer.setStartAfter()— which also delivers a general-purpose “start this layer at 18:00” capability.
The Challenge
A license shortage is not a property of the frame that hit it. Previously Cuebot could not tell one
from a generic crash, so a farm at license cap produced a wave of dead frames that someone had to
clean up by hand, every single time. Retrying immediately is pointless — the license is still gone —
and maxRetries is typically low enough that the frames died within seconds of each other.
RQD’s log-based exit-status rules gave RQD the ability to recognise the failure from the frame log and report a substitute exit status. This feature is the Cuebot half: react to that status by pausing the layer for a few minutes rather than killing its frames. Pausing the layer is correct because every frame in a layer depends on the same license — one failure is enough to establish that the pool is exhausted.
The Solution
Automatic backoff configuration
Add matching configuration to both sides:
rqd.yaml (see the Rust RQD reference):
runner:
log_exit_status_rules:
- name: "HOUDINI_LICENSE_ERROR"
regex: "A usable license to run the application is installed but they are all in use"
exit_status: 330
opencue.properties:
# Comma-separated exit_status:minutes pairs. Empty (default) disables the feature.
dispatcher.layer_delay.rules=330:5
When a frame exits 330, Cuebot marks the frame WAITING (no retry consumed), records
Automatic backoff: exit status 330 on the layer, and defers the layer’s booking for 5 minutes.
In-flight frames on the same layer reporting the same status collapse into that one write. When the
delay expires the layer books again; if the license is still gone, the next report re-delays it.
330 is the conventional license-shortage code — it sits safely outside the exit statuses Cuebot
reserves internally.
Key behaviors:
- Off by default — an empty rule list changes nothing on upgrade.
- No retries consumed — configured statuses are excluded from retry counting, so frames keep their full retry budget for genuine failures.
- Auto-eat wins — on a job with auto-eat enabled a matching failure is still eaten, so the job finishes promptly.
- Operator intent survives — the automatic write only ever moves the time later; an operator-set 18:00 start cannot be pulled earlier by a backoff, and a longer rule can extend a shorter active delay.
- Both dispatchers honour the gate — the Cuebot dispatcher (including local dispatch) and the Rust scheduler both enforce it at the frame-reservation update, the single authoritative choke point.
Operator scheduling
In CueGUI’s layer view, right-click → Set Start After… opens a picker with quick presets
(+15m, +1h, +4h, Tonight 18:00). Delayed layers show a tinted row and a Start After column whose
tooltip explains why the layer is delayed — Automatic backoff: exit status 330 or
Set by <user>. Clear makes the layer bookable immediately (though it may be re-delayed
automatically while the underlying condition persists).
From python:
layer.setStartAfter(epoch_seconds) # defer booking
layer.startAfter() # read it back (0 = not set)
layer.startAfterReason() # provenance, displayed verbatim
layer.clearStartAfter() # bookable immediately
Monitoring
Two Prometheus metrics make a broken license server loud instead of silent:
| Metric | Meaning |
|---|---|
cuebot_layer_delays_total{exit_status} |
Automatic delays written, by exit status |
cuebot_layers_delayed |
Layers currently gated |
A layer stuck re-delaying for hours shows as a flat non-zero gauge with a climbing counter — alert
on cuebot_layers_delayed > 0 sustained.
Availability
The layer start-after gate is available now in Cuebot, the Rust scheduler, pycue, and CueGUI.
CueWeb parity (a read-only column, then set/clear) and rest_gateway registration of
SetStartAfter are tracked as follow-up work.