Fix DAG import errors silently dropped when the bundle is re-instantiated inside the parsing transaction#69845
Conversation
|
Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
|
|
Had a look through this and the guard reads right to me. |
|
Thanks for the review! |
|
Thanks for fixing the no-listener case. I think there may still be a similar transaction issue when any listener plugin is registered.
For bundle types like the Git bundle, calling Would it be reasonable to pass the already-known As a side benefit, the existing-error path would no longer need the extra I tried this approach locally with a registered listener for both new and existing import errors, and the listener still received the expected filename while the |
b91f540 to
86ba347
Compare
|
Thanks @dhkim1920, that's a great catch — you're right that I've updated the PR to your suggested approach. The already-known bundle path ( The regression test now registers an import-error listener and asserts that @Vamsi-klu thanks for the earlier review as well — this approach makes the |
|
I rechecked the updated bundle-path implementation. The new direction is better, but one production caller still does not forward the path. Could you pass The title and body still describe the superseded Drafted-by: Codex (GPT-5); reviewed by @Vamsi-klu before posting |
|
Thanks @Vamsi-klu for the thorough recheck — all points addressed in 364a7d0: sync_bag_to_db() now forwards the path: it passes bundle_path=dagbag.bundle_path to update_dag_parsing_results_in_db(), so the CLI / dag.test() path no longer falls back to full_file_path() inside the transaction. |
… transaction When recording a DAG import error, _update_import_errors() called ParseImportError.full_file_path() to build the argument for the on_new/on_existing_dag_import_error listeners. full_file_path() re-instantiates the DAG bundle via DagBundlesManager().get_bundle(); for some bundle types (e.g. the Git bundle) this resolves an Airflow Connection. Doing that inside the DAG-parsing transaction, before the pending ParseImportError row is flushed, could disturb the transaction and roll the row back -- so the DAG was flagged as broken (has_import_errors) while no import error was ever shown in the UI. Thread the already-known bundle path (DagFileInfo.bundle_path) down through persist_parsing_result -> update_dag_parsing_results_in_db -> _update_import_errors and build the listener filename with str(bundle_path / relative_fileloc), so the bundle is not re-instantiated inside the transaction. full_file_path() is kept only as a fallback for callers that do not thread the bundle path. This also drops the extra select(ParseImportError) that previously existed only to feed the listener argument on the existing-error path. Approach suggested by @dhkim1920 in the PR review. Signed-off-by: kjh0623 <8412070+kjh0623@users.noreply.github.com>
… no listener is registered Address review feedback: - sync_bag_to_db() now forwards dagbag.bundle_path to update_dag_parsing_results_in_db(), so the CLI/dag.test() path no longer falls back to the bundle-instantiating full_file_path() inside the parsing transaction. - Restore a cheap has_listeners early exit so the fallback (select + full_file_path) never runs when no listener plugin is registered, regardless of whether bundle_path was threaded down. - Use the per-file bundle_name_ consistently when building the listener filename in the new-error branch. - Add regression tests: through sync_bag_to_db() end-to-end (fails if a production caller stops forwarding bundle_path), for the existing-error listener branch, and for the no-listener fallback.
…skip in test - get_listener_manager() loads listener plugins on first call, so evaluating has_listeners at the top of _update_import_errors could let a broken listener plugin abort the whole function and drop the import-error rows -- the very symptom this PR fixes. Move the check back inside the per-file try blocks so a listener-manager failure is logged, as before, without affecting error recording. - The sync_bag_to_db regression test's DAG file did not contain the string 'airflow', so DAG_DISCOVERY_SAFE_MODE (default True) would skip the file entirely and the test would fail in CI.
handle_parsing_result now forwards file.bundle_path to persist_parsing_result, so the exact-kwargs assertion in test_handle_parsing_result_updates_stats_after_successful_persist needs the new argument. Assert the actual TEST_DAGS_FOLDER value (rather than mock.ANY) so the test also verifies the bundle path is threaded through correctly. Signed-off-by: kjh0623 <8412070+kjh0623@users.noreply.github.com>
53c809e to
52ed02e
Compare
_update_import_errors()eagerly evaluatedParseImportError.full_file_path()to build theon_new/on_existing_dag_import_errorlistener arguments.full_file_path()instantiates the DAG bundle viaDagBundlesManager().get_bundle(), which for some bundle types (e.g. the Git bundle) resolves an Airflow Connection. Performing that work inside the DAG-parsing transaction can disturb it and roll back the not-yet-flushedParseImportErrorrow, so the DAG ends up flagged as broken (has_import_errors) while no import error is ever shown in the UI.Fix
DagFileInfo.bundle_path) down throughpersist_parsing_result→update_dag_parsing_results_in_db→_update_import_errors, and build the listener filename withstr(bundle_path / relative_fileloc)instead of callingfull_file_path(). The bundle is no longer re-instantiated inside the transaction, regardless of which listeners are registered.sync_bag_to_db()(used by the CLI anddag.test()) now forwardsdagbag.bundle_pathas well, so that caller is covered too (review feedback from @Vamsi-klu).has_listenersearly exit), so callers that don't threadbundle_pathdown never hit thefull_file_path()fallback inside the transaction.select(ParseImportError)query that only existed to feed the listener argument (suggested by @dhkim1920).Tests
sync_bag_to_db()end-to-end:full_file_path()raises if called, so the test fails if any production caller stops forwardingbundle_path.on_existing_dag_import_errorbranch withbundle_path.bundle_path(the original silent-drop scenario).Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code following the guidelines
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.