Repository navigation
Parse native Lang-SDK Dags in the Dag processor with their runtime - #74035
Merged
Merged
Conversation
This was referenced Oct 1, 2026
jason810496
added this pull request to stack #74038
October 1, 2026 13:38
1 task done
jason810496
removed this pull request from stack #74038
October 1, 2026 15:13
jason810496
changed the base branch from
jason/lang-sdk-e2e/02b-shared-dag-cycle-detection
to
jason/lang-sdk-e2e/03c-coordinator-dag-parsing
October 1, 2026 15:15
jason810496
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
from
October 1, 2026 15:15
6f91c3e to
1610ac7
Compare
1 task done
jason810496
added this pull request to stack #74044
October 1, 2026 15:18
kaxil
reviewed
Oct 1, 2026
jason810496
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
from
October 2, 2026 00:54
1610ac7 to
cd38d33
Compare
jason810496
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
2 times, most recently
from
October 2, 2026 05:44
b2ce95c to
e072db6
Compare
1 task done
pierrejeambrun
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
from
October 2, 2026 09:00
e072db6 to
31c1a6b
Compare
1 task done
jason810496
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
from
October 2, 2026 11:41
ea57472 to
a70eb43
Compare
The Task SDK now owns the lookup of the coordinator whose runtime parses a file, so the task runner can share it. Core keeps its logging wrapper. Its runtime SDK import is recorded in the SDK import inventory instead of being hidden with noqa, and the broken-config test uses a real clashing config.
The error now names the coordinator that parses the Dag and suggests giving the Dag's tasks their own queue, since mapping a shared queue such as default would send every Python task on it to the runtime. The task reports FAILED instead of exiting 1, so it does not retry a misconfiguration that retrying cannot fix. A broken coordinators config leaves the file to the Dag bag, which reports it.
A schema validation error now names the path of the invalid field.
A process the runtime started could keep its output open after the runtime exited. Every kill then returned early, so the parse never finished, its result was lost and the leftover kept running. Once the runtime has exited, the grace kill, the timeout kill and close() now kill its process group. The kill also waits a bounded time, so a runtime stuck in the kernel does not stall the Dag processor loop.
The import error is all a user sees of a timed-out parse, so it now names the limit to change: [core] dagbag_import_timeout or the get_dagbag_import_timeout policy, or [dag_processor] dag_file_processor_timeout before the runtime reports its import timeout.
Tests assert through these mocks, so a misspelt method would pass.
A Python Dag's tasks are checked for an executor available to the bundle's team, and tasks in the default pool move to the team's default pool. A Lang-SDK runtime's Dags now get the same: a Dag with an unavailable executor is the file's import error, and the pools are set in the stored payload. The Dag bag's helpers share the bundle team lookup so the processor can reuse them.
The test commits import error rows that the session fixture does not roll back, so they leaked into later tests.
The Dag processor manager starts the Lang-SDK processor for a coordinator-claimed file itself, which differs from the importer integration point the ADR describes. Record it as a bridge until importers own their parse process, and why.
Nothing here starts the Lang-SDK processor without an API client: the manager always passes one, and the first client-less caller is the Dag bag in a later change. Remove run(), the optional client and the gate that answered requests with an error without one, so the change that adds the caller can add them with it.
SIGKILL is delivered asynchronously, so the leftover can still show as running right after the kill.
CoordinatorManager.for_bundle now returns Dag importers, so the task runner matches the claiming coordinator through each importer.
The Dag processor always gives the Lang-SDK processor one.
Discovery now returns DagFileInfo records instead of relative paths.
A task of a native Dag that reaches a Python worker now fails with the coordinator class its Dag importer names, instead of the key of the coordinator that parses the Dag. The check no longer needs the parsing coordinator, so it also holds when several coordinators of that class are configured.
…sing get_claiming_importer replaces get_claiming_coordinator, and the Task SDK's find_claiming_coordinator is gone. The manager and the Dag bag sync only need to know whether an importer claims a file. The parse child asks the importer for its parsing coordinator, so a Dag bundle with no usable coordinator is the file's import error. The Dag source is read through the importer. The fake Lang-SDK test helpers set coordinator_classpath and register their importer in COORDINATOR_DAG_IMPORTERS.
A Dag file that no single coordinator can parse stays claimed by its importer, and its parse fails with an import error that says why: no entry in dag_bundle_to_coordinator, an entry for another class or one that cannot be loaded, or an option that is not a JSON object of coordinator keys.
validate_serialized_dag returns the Dag it deserialized, so the Lang-SDK processor uses it for the executor and pool checks instead of copying and deserializing the serialized Dag a second time.
jason810496
force-pushed
the
jason/lang-sdk-e2e/03-native-dag-parse
branch
from
October 5, 2026 09:12
79bef76 to
9007b91
Compare
pierrejeambrun
approved these changes
Oct 5, 2026
pierrejeambrun
left a comment
Member
There was a problem hiding this comment.
LGTM just one thing to address I believe.
`_register_comm` can run after the runtime has already died, so its `send_msg` call needs the same BrokenPipeError/ConnectionResetError guard `_service_processor_sockets` uses elsewhere. Co-Authored-By: Claude <noreply@anthropic.com>
jason810496
commented
Oct 5, 2026
jason810496
left a comment
Member
Author
There was a problem hiding this comment.
Thanks for the review!
This was referenced Oct 5, 2026
1 task done
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack (bottom to top): #74042, #74035, #74043, #74036, #74037, #73845, #73846, #73847
Why
Nothing can parse a Dag written entirely in a Lang SDK yet. This is the Dag processor side of the
parse_daghalf of #71929.What changes
CoordinatorDagImporterwith the newLangSDKDagFileProcessorProcess(dag_processing/lang_sdk_processor.py), and every other file as before. A callback for such a file is dropped with a warning before the file is queued.get_dagbag_import_timeoutfor the file, asks the file's importer for its coordinator and execs the runtime, which connects back to the Dag processor over TCP and answers the parse request. Fork, the macOS exec path and log forwarding work as for a Python file (Move the Dag file processor's shared plumbing into a base class #74040).fill_config_defaultsand must passvalidate_serialized_dag(Validate a serialized Dag and fill its unset settings from the Airflow config #74041). A failed start, a missing result, an invalid frame or message, an invalid Dag, or a parse past its timeout gives an import error. A runtime still running 5s after its result is killed, with anything left in its process group. A native Dag gets the same multi-team executor and pool checks as a Python Dag. The file's Dag source is read with its Dag importer.sync_bag_to_dbleaves the file's import errors to the Dag processor. Parse native Lang-SDK Dags in a Dag bag #74043 adds the Dag bag path.Limitations
DAGclass enforces, such as that a scheduled Dag's required params have defaults, is not checked.Deviations from #71929
parse_dagis onSubprocessCoordinatoronly.Follow-ups
Serde.kt(Java SDK: Serialize native Dags to DagSerialization v3 #71190) still writes the stock values of the five config settings, so a native Java Dag does not get the config values yet. The Go SDK serializer (Support TaskFlow Dag definitions natively in the Go-SDK #70158) writes them too.CoordinatorDagImporter, and a packed Go bundle has no file extension to claim.airflow-core/adr/lang-sdk/0009-provider-operators-as-generated-dsl.mdsays a provider DSL task runs on a Python worker, which a task of a native Dag cannot do. It needs its own amendment.Was generative AI tooling used to co-author this PR?