Skip to content

Don't deactivate DAG bundles owned by other dag-processors#69964

Merged
hussein-awala merged 1 commit into
apache:mainfrom
sortega:sortega/fix-dag-processor-partial-bundle-config
Jul 17, 2026
Merged

Don't deactivate DAG bundles owned by other dag-processors#69964
hussein-awala merged 1 commit into
apache:mainfrom
sortega:sortega/fix-dag-processor-partial-bundle-config

Conversation

@sortega

@sortega sortega commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Why

DagBundlesManager.sync_bundles_to_db() marks every bundle stored in the DB that is not present in the calling process's config as inactive ("no longer found in config and has been disabled"). This implicitly assumes the calling process sees the complete bundle configuration.

When multiple dag-processor processes are each configured with a partial bundle config — one bundle per processor, a natural way to shard DAG parsing — each processor treats every other processor's bundle as removed and deactivates it. Processor A disables B's bundle, B then disables A's, and they flip dag_bundle.active on every parse cycle. The deployment never converges and continuously logs the disable warning for bundles that are actively configured on another processor.

Minimal reproduction of the flip-flop (two managers with disjoint config, no error path involved):

AFTER B syncs:       [('bundle-a', False), ('bundle-b', True)]   # B disabled A
AFTER A syncs again: [('bundle-a', True),  ('bundle-b', False)]  # A disabled B

How

  • Add a deactivate_missing parameter to sync_bundles_to_db(), defaulting to True so existing single-processor / full-config behavior (including cleanup of genuinely-removed bundles) is unchanged.
  • When deactivate_missing=False, the method upserts the bundles it knows about and returns without touching the rest.
  • DagFileProcessorManager.sync_bundles() now passes deactivate_missing=not self.bundle_names_to_parse: a processor started with --bundle-name (a partial owner) will not deactivate bundles it does not own, while an unfiltered processor keeps deactivating removed bundles as before.

Tests

  • test_sync_bundles_to_db_partial_config_does_not_disable_other_bundles — two processors with disjoint configs; asserts both bundles stay active across sync cycles (fails without the fix).
  • test_sync_bundles_deactivates_missing_when_owning_all_bundles / test_sync_bundles_does_not_deactivate_missing_when_filtered — assert sync_bundles() forwards the right deactivate_missing value based on bundle_names_to_parse.
  • Existing test_sync_bundles_to_db (full-config deactivation) still passes.

closes: #69963
related: #69698


Was generative AI tooling used to co-author this PR?
  • Yes - Claude Code

sortega added a commit to sortega/airflow that referenced this pull request Jul 16, 2026

@hussein-awala hussein-awala left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I reproduced the issue locally and confirmed the fix resolves it. Please drop the newsfragment (we keep those for behavior changes, migrations, or must-highlight items, otherwise the commit message is enough), then LGTM.

Comment thread airflow-core/newsfragments/69964.bugfix.rst Outdated
`DagBundlesManager.sync_bundles_to_db()` marks every stored bundle that is
not in the calling process's config as inactive. This assumes the caller
sees the complete bundle configuration.

When multiple dag-processors are each configured with a partial config (one
bundle per processor, a natural way to shard parsing), each processor treats
the other processors' bundles as "no longer found in config" and disables
them. Processor A disables B's bundle, B disables A's, and they flip
`dag_bundle.active` on every parse cycle -- the deployment never converges
and continuously logs "DAG bundle ... is no longer found in config and has
been disabled" for bundles that are actively configured elsewhere.

Add a `deactivate_missing` flag (default `True`, preserving existing
single-processor behavior) and have `DagFileProcessorManager.sync_bundles()`
pass `deactivate_missing=False` when the processor was started with a bundle
filter (`--bundle-name` / `bundle_names_to_parse`), i.e. when it only owns a
subset of the bundles.

closes: apache#69963
related: apache#69698

Generated-by: Claude Code following the guidelines
@sortega
sortega force-pushed the sortega/fix-dag-processor-partial-bundle-config branch from a96da4a to d01ff90 Compare July 16, 2026 15:18
@eladkal eladkal added this to the Airflow 3.3.1 milestone Jul 16, 2026
@eladkal eladkal added type:bug-fix Changelog: Bug Fixes backport-to-v3-3-test Backport to v3-3-test labels Jul 16, 2026
@eladkal
eladkal requested a review from hussein-awala July 16, 2026 17:08

@eladkal eladkal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hussein-awala
hussein-awala merged commit 038ece6 into apache:main Jul 17, 2026
78 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-3-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
v3-3-test PR Link

@sortega
sortega deleted the sortega/fix-dag-processor-partial-bundle-config branch July 17, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:DAG-processing backport-to-v3-3-test Backport to v3-3-test type:bug-fix Changelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple dag-processors with partial bundle configs deactivate each other's bundles

3 participants