The one Oban worker behind every job run: it does one batch of a run and hands the next to Oban through the engine.
An Oban job here is %{"run_uuid", "generation", "kind"}. The flow:
- claim the run for this generation (
Engine.claim/2): an older generation or a run that is paused, cancelled or finished does nothing (:ok), and a run another batch still holds is snoozed. This comes first, before anything else is looked at, so a delivery that is not the run's current dispatch is inert whatever else is true — including a kind that has since disappeared; - the kind is looked up from the claimed run; a kind that is gone (its module disabled or removed) fails the run ("kind unavailable") by checkpointing the failure with the claim just taken, rather than looping;
- call
kind.batch/1, rescuing a raise, an exit or a throw as an error; - checkpoint (
Engine.checkpoint/4): progress, cursor, the next dispatch and the history, in one transaction.
An error that Oban will retry releases the claim and is returned, so the retry
can take it; the last attempt fails the run. A timeout/1 kill leaves the
claim held — PhoenixKit.Jobs.SweepWorker releases it once Oban says the job is
no longer executing.
uniqueness is on run_uuid + generation: the same dispatch cannot be
inserted twice. It does not serialise execution — the claim does.
Summary
Functions
Runs one batch of run and answers what the state machine takes: the kind's
return, normalised, with a raise, an exit or a throw as an error. final? says
whether Oban has no attempts left (an error then fails the run instead of
being retried). Also used by inline execution.
Functions
@spec batch_outcome(module(), PhoenixKit.Jobs.Run.t(), boolean()) :: PhoenixKit.Jobs.StateMachine.outcome()
Runs one batch of run and answers what the state machine takes: the kind's
return, normalised, with a raise, an exit or a throw as an error. final? says
whether Oban has no attempts left (an error then fails the run instead of
being retried). Also used by inline execution.