Runtime dependency resolution for workflow jobs.
Called at the start of each perform/1. Loads the current job's node to get
its dependencies and flags, then resolves the state of each dependency by
joining workflow_nodes to oban_jobs.
States and outcomes
| Dep state | Default outcome | With ignore option |
|---|---|---|
completed | proceed | n/a |
executing | snooze (or stale -> cancel) | snooze |
available | snooze | snooze |
scheduled | snooze | snooze |
retryable | snooze | snooze |
cancelled | cancel this job | treat as done |
discarded | cancel this job | treat as done |
| pruned/nil | cancel (job pruned) | n/a |
A dep whose Oban job was pruned comes back from the LEFT JOIN with a nil
state and is treated as pruned. A dep stuck in executing past the stale
threshold is treated as failed rather than snoozing forever.
Ordering edges are not dependencies
A node's sequence_after is resolved separately and by a weaker rule: it
snoozes while the predecessor is pending and proceeds on every terminal
state, failures included. It is how the sequential fan-out gate paces an
expansion, and no data flows along it — the successor reads nothing the
predecessor produced, so a predecessor that dies has nothing to invalidate.
Treating it as a dep is what let one exhausted fan-out branch kill a whole
run. The branch was discarded; its successor read a failed dependency and
cancelled; the next successor cancelled on that; and the cascade arrived
at the reader configured to tolerate precisely this case
(ignore_discarded: true) as a wall of cancelled deps, which that flag
does not cover. Every completed step in the run was discarded with it.
Caveat: the stale threshold must exceed your longest step
The executing-too-long check cannot distinguish a genuinely stuck step
from a healthy long-running one. If a step can legitimately run longer than
Baton.Config.stale_executing_threshold_seconds/0 (default 600), raise that
threshold above the step's timeout — otherwise a running step is cancelled
and its dependents cascade-fail. See
Baton.Config.stale_executing_threshold_seconds/0.
Summary
Functions
Whether all upstream deps for the given job are satisfied.
Types
@type result() :: :ok | {:snooze, pos_integer()} | {:cancel, String.t()}
Functions
@spec deps_satisfied?(Oban.Job.t()) :: result()
Whether all upstream deps for the given job are satisfied.
:ok— proceed withperform_workflow/1{:snooze, seconds}— some deps still pending, recheck later{:cancel, reason}— a dep failed permanently