Language SDK Spec¶
This document fixes the terms an Airflow Language SDK (Go, Java, TypeScript, …) uses for its user-facing authoring interface, and how they fit together. Every SDK spells them in its own language’s idiom; the terms and the flow are the same everywhere.
Spec version: 1.0.
There are two authoring features, and they differ in one thing: who owns the graph.
FEATURE 1 FEATURE 2
Mixed Language Task Handler Native Dag
Python owns the graph the SDK owns the graph
Python @task.stub Dag(spec)
declares dag_id, task_id, |
arguments, and every edge v
| dag <-- owns the schedule,
| binds by dag_id + task_id | the tasks, the edges
v v
fn --> TaskHandler(dagId, taskId, fn) fn --> dag.Task(fn, options)
| |
v v
TaskHandlerRef TaskRef
| |
| | Inputs(ref) data edge, carries a value
| | before / after order edge, carries nothing
| v
| TaskRef
| |
+---------------------+---------------------+
|
v
bundle.register(Dag | TaskHandler)
|
v
bundle.serve() <-- the task subprocess entrypoint
A TaskHandler supplies a body for a task Python already declared, so it names the
dagId/taskId pair it binds to and nothing else. A native Dag owns the schedule, the
tasks, and the edges, so dag.Task returns a TaskRef that edges attach to. Both features
land in the same bundle, and one bundle.serve() call serves both, so a single process can carry
native Dags and mixed-language task handlers at once.
Terms¶
Term |
Definition |
|---|---|
|
The function callable itself: the task body a user writes. |
|
Callable interface factory over |
|
Callable interface factory over a Dag spec; returns a |
|
The instance a |
|
Callable interface factory over |
|
Holds every |
|
A method on the |
Per-SDK spelling¶
Term |
Go |
Java |
TypeScript |
|---|---|---|---|
|
a |
an annotated method, or an |
an |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data edge |
|
the |
the task factory call |
order edge |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Task subprocess lifecycle¶
Authoring is only half the contract. Every SDK runs the same sequence inside the task subprocess, once per task instance:
1 process start
2 receive StartupDetails from the supervisor
3 build Context + Client, bind the cancellation signal
4 look up the registered fn for (dag_id, task_id)
5 bind arguments: TaskFlow data, plus ctx/client where they are injected
6 +-- scope holding Context + Client --+
| invoke fn | <-- a getter reads this scope
+------------------------------------+
7 push the return value to XCom, report the terminal state
Steps 2 through 5 and step 7 belong to the SDK; step 6 is the only one that runs code a user
wrote. How fn reaches Context and Client is each SDK’s own choice — parameters, or
getters that read the scope opened at step 6 — and all this spec asks is that fn receives the
same pair the SDK built at step 3. The terminal state at step 7 is one of SucceedTask,
RetryTask, or TaskState, and it is reported exactly once.