Ephemeral execution shell for one claimed run.
Each vehicle loads and compiles the run's exact graph, validates every
explicit node timeout against the host's finite attempt maximum, and
commits one fenced runtime moment at a time. Host-policy incompatibility
reschedules the claim without poisoning: the claim-attempt increment is
reversed, the run stays valid, and the handback counts one claim abandon.
The retry wake backs off exponentially with the consecutive abandon
count — min(abandon_backoff_ms * 2^abandons, abandon_backoff_cap_ms) —
so a fleet with no compatible host pushes the run back instead of
spinning, and any committed progress resets the count. Stored-graph
incompatibility shares the same abandon counter, so a persistently
incompatible deployment still poisons through that path's budget.
Deployments should still use homogeneous limits and audit stored graphs
before rollout so compatible work is not needlessly delayed.
Node attempt deadlines are enforced by the runtime dispatcher. The cooperative drain budget is checked only at moment boundaries and includes configured headroom below orphan-TTL crash recovery. Token/sequence fencing remains the sole authority for commits after a crash or steal.
Vehicles never refresh claims. Attempt timeout and retry are replay boundaries: external effects and unlinked children cannot be retracted, so expected long work must park or detach durably.
Summary
Functions
Synchronously drains one claim lease to its next park or stop.
Launches a vehicle under the configured :task_supervisor.
Builds the dispatcher's :launch callback from eagerly validated options.
Types
@type drain_budget() :: [ max_moments: pos_integer() | :infinity, max_elapsed_ms: pos_integer() | :infinity ]
@type option() :: {:backend, {module(), Docket.Backend.ctx()}} | {:task_supervisor, Supervisor.supervisor()} | {:clock, (-> DateTime.t())} | {:monotonic_clock, (-> integer())} | {:drain_budget, drain_budget()} | {:max_attempt_elapsed_ms, pos_integer()} | {:jitter, (pos_integer() -> non_neg_integer())} | {:abandon_backoff_ms, pos_integer()} | {:abandon_backoff_cap_ms, pos_integer()} | {:max_claim_abandons, pos_integer()} | {:graph_cache, module() | false} | {:graph_cache_opts, keyword()} | {:compiler, (Docket.Graph.t(), keyword() -> {:ok, Docket.Runtime.Graph.t()} | {:error, Docket.Graph.t()})} | {:executor, module()} | {:executor_opts, keyword()} | {:max_supersteps, pos_integer()} | {:context, map()} | {:id_generator, (atom() -> String.t())} | {:checkpoint_observers, module() | [module()]}
@type outcome() :: {:ok, {:parked, Docket.Runtime.Moment.park_kind()} | :fence_lost | {:discarded, term()} | {:host_incompatible, Docket.Error.t()} | {:abandoned, :rescheduled | :poisoned | :stale, term()} | {:deferred, :rescheduled | :poisoned | :stale}}
Result of one drain.
{:parked, kind} drained to a committed park. :fence_lost and
{:discarded, reason} stopped without commit authority.
{:host_incompatible, error} released without poisoning because this
host's attempt maximum cannot execute the graph. {:abandoned, ...} is
a stored-graph incompatibility; {:deferred, ...} has no due attempt yet.
Functions
@spec drain(Docket.Backend.RunStore.claim_lease(), [option()]) :: outcome()
Synchronously drains one claim lease to its next park or stop.
@spec launch(Docket.Backend.RunStore.claim_lease(), [option()]) :: {:ok, pid()} | {:error, term()}
Launches a vehicle under the configured :task_supervisor.
Shaped for the dispatcher's :launch callback:
launch: &Docket.Postgres.Vehicle.launch(&1, opts). Prefer launcher/1,
which validates the options once at assembly time.
@spec launcher([option()]) :: (Docket.Backend.RunStore.claim_lease() -> {:ok, pid()} | {:error, term()})
Builds the dispatcher's :launch callback from eagerly validated options.
Validation happens in this call, so a malformed :drain_budget or
:monotonic_clock raises ArgumentError where the supervision tree is
built - before any vehicle launches or any claim is consumed - instead
of failing per claim. This is the recommended wiring:
launch: Docket.Postgres.Vehicle.launcher(opts).