Baton.Check (Baton v0.27.4)

Copy Markdown View Source

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 stateDefault outcomeWith ignore option
completedproceedn/a
executingsnooze (or stale -> cancel)snooze
availablesnoozesnooze
scheduledsnoozesnooze
retryablesnoozesnooze
cancelledcancel this jobtreat as done
discardedcancel this jobtreat as done
pruned/nilcancel (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

result()

@type result() :: :ok | {:snooze, pos_integer()} | {:cancel, String.t()}

Functions

deps_satisfied?(job)

@spec deps_satisfied?(Oban.Job.t()) :: result()

Whether all upstream deps for the given job are satisfied.

  • :ok — proceed with perform_workflow/1
  • {:snooze, seconds} — some deps still pending, recheck later
  • {:cancel, reason} — a dep failed permanently