Jobs
New to the SDK? Getting started shows how to connect and use it.
Jobs
The jobs of one workspace.
Jobs.trigger()
trigger(
*,
refs: Sequence[str] | None = None,
selectors: Sequence[str] | None = None,
profile: str | None | Keep = KEEP,
refresh: bool = False,
dry_run: bool = False,
) -> tuple[TriggerResult, ...]
Ask several jobs to run, by ref or by selector.
Unlike Job.start_run(), this does not take a trigger of its own.
A job named in refs fires its default_trigger (or a manual
trigger when it has none); a job matched by selectors fires the
trigger it matched, preferring its default_trigger when that matched
too.
Arguments
| Name | Type | Description |
|---|---|---|
refs | Sequence[str] | None | Job refs to trigger. Each resolves to exactly one job. |
selectors | Sequence[str] | None | Trigger patterns to match, fnmatch-style — for example "tag:backfill", "schedule:*", "manual:jobs.mod.*". |
profile | str | None | Keep | Profile for every run started. Omit for each job's default. |
refresh | bool | Start the jobs that do start as a refresh, as for Job.start_run(). Downstream jobs that depend on their freshness are reset too. Ignored for a job whose refresh_propagation is "block". |
dry_run | bool | Report what would be triggered without starting anything. |
Returns: tuple[TriggerResult, ...] — One result per matched job; awaitable in async mode. Started jobs come first, then skipped ones, each in the platform's dependency order. A job the platform declined is present too, with its reason — see TriggerResult.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotAuthorized | The caller lacks the access this call needs; message says why. |
NotFound | A ref names no job in this workspace, or only an archived one. |
ScopeMissing | Reached without a workspace in scope. |
ValueError | Neither refs nor selectors was given. |
Jobs.deploy_manifest()
deploy_manifest(
manifest: DeployManifest,
*,
manifest_hash: str,
deployment_module: str | None = None,
description: str | None | Keep = KEEP,
dry_run: bool = False,
) -> DeployReport
Reconcile the workspace's jobs against a deployment manifest.
The job definitions are passed through as the manifest carries them.
Upload the code with Deployments.upload() first — this registers
what runs, not what it runs from.
Arguments
| Name | Type | Description |
|---|---|---|
manifest | DeployManifest | The manifest to deploy, as dlt built it. Its jobs and engine version travel together, so the two cannot be crossed. |
manifest_hash | str | Content hash of that manifest, from dlt's generate_manifest_hash. |
deployment_module | str | None | The deployment module this deploy claims. None, the default, is an ad-hoc deploy: jobs are added and updated but never archived. Naming one lets the platform archive the jobs that module owns and the manifest no longer lists. |
description | str | None | Keep | Workspace description, applied only when deployment_module is "__deployment__". Omit, or pass None, to leave it as it is. |
dry_run | bool | Report the plan without persisting it. Jobs in a dry-run report that are not yet deployed carry a placeholder id and cannot be acted on. |
Returns: DeployReport — What was added, updated, left alone and archived; awaitable in async mode.
Raises
| Exception | When |
|---|---|
BadRequest | The request was rejected as invalid; message, code and fields say why. |
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotAuthorized | The caller lacks the access this call needs; message says why. |
ScopeMissing | Reached without a workspace in scope. |
ValueError | The manifest lists no jobs. |
Jobs.get()
get(*, id: str) -> Job
Return one job by id.
Arguments
| Name | Type | Description |
|---|---|---|
id | str | The job's uuid. To look a job up by its ref, use get_by_ref(). |
Returns: Job — The job; awaitable in async mode.
Raises
| Exception | When |
|---|---|
BadRequest | The request was rejected as invalid; message, code and fields say why. |
NotFound | No such job in this workspace. |
ScopeMissing | Reached without a workspace in scope. |
Jobs.get_by_ref()
get_by_ref(ref: str) -> Job
Return one job by its ref, archived or not.
Arguments
| Name | Type | Description |
|---|---|---|
ref | str | The job ref, e.g. jobs.load. |
Returns: Job — The job; awaitable in async mode.
Raises
| Exception | When |
|---|---|
NotFound | No job in this workspace has that ref. |
ScopeMissing | Reached without a workspace in scope. |
Jobs.count()
count(*, archived: bool | Keep = KEEP) -> int
Return how many jobs the workspace has, without fetching them.
Arguments
| Name | Type | Description |
|---|---|---|
archived | bool | Keep | As for list(). |
Returns: int — The job count; awaitable in async mode. Saturates at 10,001, so a value equal to that means "at least this many".
Raises
| Exception | When |
|---|---|
ScopeMissing | Reached without a workspace in scope. |
Jobs.list()
list(
*,
archived: bool | Keep = KEEP,
limit: int | None = None,
offset: int = 0,
) -> Iterable[Job] | AsyncIterable[Job]
Yield the jobs in the workspace, paging lazily.
Platform errors are raised when iteration begins, not by this call.
Arguments
| Name | Type | Description |
|---|---|---|
archived | bool | Keep | Keep only archived jobs, or only live ones. Omit for both, which is what the platform returns when nothing filters. |
limit | int | None | Return at most this many jobs. None walks to the end, or to row 10,100, past which the platform does not page. |
offset | int | Skip this many jobs, server-side. |
Returns: Iterable[Job] | AsyncIterable[Job] — An iterable of jobs; async-iterable in async mode.
Raises
| Exception | When |
|---|---|
ScopeMissing | Reached without a workspace in scope. |
ValueError | A negative limit or offset. |
Job
A deployed job in a workspace.
| Name | Type | Example | Description |
|---|---|---|---|
job.runs | JobRuns | job.runs.list() | This job's runs. |
Attributes
| Name | Type | Description |
|---|---|---|
job_ref | str | Canonical job reference, unique per workspace. |
id | str | Unique ID (a UUID). |
name | str | None | Display name for the job. |
job_type | JobType | The type of the job: batch, interactive, or stream. |
is_paused | bool | Whether the job's scheduled runs are paused. The scheduler does not start it, including a scheduled run that was waiting for its upstream jobs; manual runs, runs started by a trigger request, and runs started by another job's success or failure still run. Only a job with next_scheduled_run_at can be paused, and a deploy that removes the schedule clears the pause. |
is_archived | bool | Whether the job is archived. Archived jobs cannot be run and their public URL stops working. |
version | int | Version number, starting at 1 and incremented by each update to the job: a job's current version, or a job version's own number. |
public_url | str | None | The public URL where the job can be accessed without authentication; None when the job is not published. It does not work while the job is archived. |
job_url | str | None | The URL of the job in the web app for an interactive job; None otherwise. |
default_trigger | str | None | The trigger fired when a run is started without naming one, computed from the job definition. |
triggers | tuple[str, ...] | Every trigger the job answers to, computed from its definition; selectors match against these. |
next_scheduled_run_at | datetime | None | When the job is next scheduled to run; None if it has no schedule. |
job_definition | Mapping[str, Any] | The job definition from the manifest, migrated to the platform's current format. Left opaque: it is dlt's own nested structure, and the SDK models none of it — as with the definitions Jobs.deploy_manifest accepts. |
created_at | datetime | When it was created. |
Job.pause()
pause() -> Job
Suspend the job's schedule.
Pausing a paused job changes nothing.
Returns: Job — A fresh snapshot with is_paused set; awaitable in async mode.
Raises
| Exception | When |
|---|---|
BadRequest | The request was rejected as invalid; message, code and fields say why. |
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.resume()
resume() -> Job
Resume the job's schedule.
Resuming a job that is not paused changes nothing.
Returns: Job — A fresh snapshot with is_paused cleared; awaitable in async mode.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.publish()
publish() -> Job
Expose the job on a public trigger URL.
Calling it again issues a new URL and invalidates the previous one.
Returns: Job — A fresh snapshot carrying public_url; awaitable in async mode.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.unpublish()
unpublish() -> Job
Withdraw the job's public trigger URL.
Unpublishing a job that is not published changes nothing.
Returns: Job — A fresh snapshot with public_url cleared; awaitable in async mode.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.archive()
archive() -> Job
Retire the job so it can no longer run, manually or on schedule.
Its schedule, default trigger and pause are cleared. List it with
archived=True. Archiving an archived job changes nothing.
Returns: Job — A fresh snapshot with is_archived set; awaitable in async mode.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.unarchive()
unarchive() -> Job
Let an archived job run again.
Its schedule and default trigger are restored from its definition; a pause is not. Unarchiving a live job changes nothing.
Returns: Job — A fresh snapshot with is_archived cleared; awaitable in async mode.
Raises
| Exception | When |
|---|---|
Conflict | The current state does not allow the call, e.g. the workspace is archived; code and message say why. |
NotFound | The job no longer exists. |
Job.start_run()
start_run(
*,
trigger: str = MANUAL_TRIGGER,
profile: str | None | Keep = KEEP,
refresh: bool = False,
skip_freshness: bool = False,
) -> JobRun
Start a run of this job.
A run the platform declines to start raises, with its code naming why
and the platform's reasons in fields.
Arguments
| Name | Type | Description |
|---|---|---|
trigger | str | Which trigger to fire, in canonical form. Defaults to "manual:". Only the form is validated, so a trigger the job definition does not declare is still honoured. |
profile | str | None | Keep | Profile to run under. Omit for the job's default. |
refresh | bool | Start as a refresh: the job's progress goes back to its interval start and the run receives refresh=True in its run context; what to reload is up to the job's code. Downstream jobs that depend on its freshness are reset too. Ignored when the job's refresh_propagation is "block". |
skip_freshness | bool | Start even when the upstream jobs this job's freshness constraints name are not fresh. |
Returns: JobRun — The run that started; awaitable in async mode.
Raises
| Exception | When |
|---|---|
BadRequest | The request was rejected as invalid; message, code and fields say why. |
Conflict | The platform declined to start a run, e.g. an upstream is not fresh, the job is outside its interval, or a concurrency limit is reached; code says which. Also raised when the workspace is archived. |
NotAuthorized | The caller lacks the access this call needs; message says why. |
NotFound | No such job in this workspace. |
ScopeMissing | Reached without a workspace in scope. |
DeployReport
What a manifest deploy did to a workspace's jobs.
Attributes
| Name | Type | Description |
|---|---|---|
added | tuple[Job, ...] | Jobs the manifest introduced. |
updated | tuple[Job, ...] | Jobs it changed, at their new version. |
unchanged | tuple[Job, ...] | Jobs it left alone. |
archived | tuple[Job, ...] | Jobs it removed, which happens only for a module deploy. |
warnings | tuple[str, ...] | Always empty at present. |
deployment_module | str | None | The deployment module the deploy was scoped to. |
TriggerResult
The outcome of asking a job to run through Jobs.trigger().
Asking does not guarantee a run: the platform skips a trigger it cannot
honour and says why, so check started before expecting job_run_id.
A dry run creates no run, so job_run_id is None there too.
Attributes
| Name | Type | Description |
|---|---|---|
job_ref | str | The job reference of the matched job. |
job_id | str | The ID of the matched job. |
status | TriggerStatus | Whether a run started, or why it did not. |
reasons | tuple[str, ...] | Human-readable reasons for a skip, e.g. which upstream jobs are not fresh; None when the job was triggered or no reasons were recorded. |
trigger | str | The trigger the job fires with. |
job_run_id | str | None | The ID of the created run; None in dry-run mode or when skipped. |
job_run_number | int | None | Number of the run within its job, counting up from 1; numbers repeat across jobs. |
matched_triggers | tuple[str, ...] | Every trigger that selected this job: its default trigger when named in job_ids, plus any selector matches. |
started | bool | Whether the platform started a run, or would in a dry run. |
DeployManifest
The part of a dlt deployment manifest a deploy reads.
Read-only and a subset, so dlt's own manifest type satisfies it structurally and the SDK needs no dependency on dlt to say what it accepts.
Attributes
| Name | Type | Description |
|---|---|---|
engine_version | int | Manifest engine version the definitions were written for. |
jobs | Sequence[Mapping[str, Any]] | Job definitions, exactly as the manifest carries them. |
JobType
How a job executes.
Members
| Member | Value | Description |
|---|---|---|
BATCH | 'batch' | Runs to completion and exits. |
INTERACTIVE | 'interactive' | Serves an interactive session. |
STREAM | 'stream' | Runs continuously. |
UNKNOWN | 'unknown' | A type this SDK version does not know. |
TriggerStatus
What became of a request to run a job.
Members
| Member | Value | Description |
|---|---|---|
TRIGGERED | 'triggered' | A run was created. |
SKIPPED_PAUSED | 'skipped_paused' | The job's schedule is suspended. |
SKIPPED_FRESH | 'skipped_fresh' | A job its freshness constraints depend on is not fresh yet; reasons names which. |
SKIPPED_ALREADY_COVERED | 'skipped_already_covered' | A completed run already covers this period. |
SKIPPED_OUT_OF_INTERVAL | 'skipped_out_of_interval' | Outside the job's configured window. |
SKIPPED_UPSTREAM_PENDING | 'skipped_upstream_pending' | A job it depends on is triggered in the same request; this job runs once that one completes. |
SKIPPED_CONCURRENCY_LIMIT | 'skipped_concurrency_limit' | The job already has as many active runs as its concurrency limit allows. |
SKIPPED_ORG_CONCURRENCY_LIMIT | 'skipped_org_concurrency_limit' | The organization is at its run limit. |
SKIPPED_MINUTES_LIMIT | 'skipped_minutes_limit' | The plan's compute minutes are exhausted. |
SKIPPED_TRIAL_EXPIRED | 'skipped_trial_expired' | The trial has ended. |
SKIPPED_WORKSPACE_ARCHIVED | 'skipped_workspace_archived' | The workspace is archived. |
UNKNOWN | 'unknown' | A status this SDK version does not know. |