Skip to content

Support TaskFlow Dag definitions natively in the Go-SDK - #70158

Draft
jason810496 wants to merge 8 commits into
apache:mainfrom
jason810496:feature/go-sdk/taskflow-syntax
Draft

Support TaskFlow Dag definitions natively in the Go-SDK#70158
jason810496 wants to merge 8 commits into
apache:mainfrom
jason810496:feature/go-sdk/taskflow-syntax

Conversation

@jason810496

@jason810496jason810496 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Why

The base Go SDK authoring API wires dependencies with string task IDs, which is typo-prone and does not carry upstream values. This PR makes dependencies follow typed data flow while retaining an explicit ordering-only option.

Example

Before this PR, native task dependencies are optional string slices:

dag:=registry.AddDag("etl", v1.DagSpec{Schedule: "@daily"})
dag.AddTask(extract)
dag.AddTask(transform, []string{"extract"})
dag.AddTask(load, []string{"transform"}, v1.TaskSpec{Retries: 2})

With this PR, task references express both data and ordering relationships:

dag:=registry.AddDag(v1.DagSpec{DagId: "etl", Schedule: "@daily"})
extracted:=dag.Task(extract)
transformed:=dag.Task(transform, v1.Inputs(extracted))
dag.Task(load, v1.Inputs(transformed), v1.TaskSpec{Retries: 2})
cleanup:=dag.Task(cleanupFn, v1.After(transformed))
_=cleanup

How

  • Replace AddTask and AddTaskWithName with Dag.Task(fn, opts...), which returns a TaskRef and accepts TaskSpec, Inputs, and After options.
  • Move Dag and task identity into DagSpec.DagId and TaskSpec.TaskId, with function names remaining the default task IDs.
  • Validate input counts, compatible Go types, same-Dag references, and ordering relationships during Dag registration.
  • Pull upstream return-value XComs at runtime and decode them into downstream typed data parameters.
  • Keep the existing bundle examples semantically unchanged and use the separate native_dag to showcase typed native authoring.
  • Do not add native Dag coverage to the Airflow E2E test until DagImporter is wired up.

Was generative AI tooling used to co-author this PR?
  • Yes, with help of Claude Code Fable 5 and Codex (GPT-5) following the guidelines

@jason810496jason810496 self-assigned this Jul 21, 2026
@jason810496
jason810496force-pushed the feature/go-sdk/taskflow-syntax branch 3 times, most recently from 04c6c1b to 0ea0905CompareJuly 21, 2026 07:15
@jason810496
jason810496force-pushed the feature/go-sdk/taskflow-syntax branch 2 times, most recently from 8ec3ab9 to ecff8f0CompareAugust 20, 2026 09:08
Native bundle registration bypasses Python-side validation, so invalid scheduling, identifiers, and task execution flags must be enforced in the Go runtime.
@jason810496
jason810496force-pushed the feature/go-sdk/taskflow-syntax branch from ecff8f0 to 0d9ad95CompareAugust 21, 2026 03:15
Dependency-only task declarations should not need an empty TaskSpec value.
@jason810496
jason810496force-pushed the feature/go-sdk/taskflow-syntax branch from 0d9ad95 to 3d074b6CompareAugust 21, 2026 07:23
Dag.Task(fn, opts...) replaces AddTask/AddTaskWithName and returns a
*TaskRef handle. Passing handles via v1.Inputs(...) wires the dependency
edge and feeds each upstream return value into the matching data
parameter of the task function at run time: the runtime pulls the
upstream return-value XCom and strictly decodes it into the declared
parameter type, so a Go dag reads like plain function composition:
d := reg.AddDag(v1.DagSpec{DagId: "etl", Schedule: "@daily"})
extracted := d.Task(extract)
d.Task(transform, v1.Inputs(extracted))
v1.After(...) declares ordering-only edges. Task ids move into the
specs: TaskSpec.TaskId (generated from schema.json as an identity
field) and DagSpec.DagId replace positional ids and AddTaskWithName.
Mismatched input counts or types, refs from another dag, and
non-decodable parameters all panic at registration, i.e. dag-parse
time.
@jason810496
jason810496force-pushed the feature/go-sdk/taskflow-syntax branch from 3d074b6 to 35f50c4CompareAugust 21, 2026 12:29
jason810496 added a commit to jason810496/airflow that referenced this pull request Aug 24, 2026
Review found serde.go's serializeTaskGroup described as shipped
present-tense fact; it only exists on the unmerged apache#67155/apache#70158
branches, same class of mistake ADR 7 already had to fix. Also split
the ShortCircuit/Branch examples' func declarations out of the
registration-statement fences to match ADR 7's presentation, since a
package-level func decl mixed with := statements isn't valid Go as
written.
jason810496 added a commit to jason810496/airflow that referenced this pull request Aug 24, 2026
…s current shape
Review found apache#70158's own registry.go still exposes After(refs...);
"Inputs is the only way to wire a dependency" read as a factual claim
about that branch rather than what it actually is, a simplification
this ADR proposes on top of it. Also cited serialized_objects.py
instead of schema.json for where task_type/_task_module actually get
written, since schema.json only declares the fields as required.
jason810496 added a commit to jason810496/airflow that referenced this pull request Aug 25, 2026
Add ADRs for the Mixed Lang Dag interface already shipped via apache#70209,
the proposed Native Dag interface (apache#67155/apache#70158), and the common task
constructs a native Go author will need next (TaskGroup, ShortCircuit,
Branch, TriggerDagRun). Recording the rationale here gives reviewers
and future contributors a single reference for these tradeoffs instead
of reconstructing them from scattered PR discussions.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jason810496