Uh oh!
There was an error while loading. Please reload this page.
Speed up Trigger.clean_unused query to prevent Triggerer crashes - #68244
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
|
c0f8d0c to
725b143CompareThere was a problem hiding this comment.
Pull request overview
This PR optimizes Trigger.clean_unused() by switching from an OUTER JOIN + GROUP BY/HAVING count-based approach to a NOT EXISTS-style anti-join when identifying unused triggers, and adds row-level locking with SKIP LOCKED to reduce interference when multiple triggerers are running concurrently.
Changes:
- Replace JOIN/aggregate “no TaskInstance rows” check with
~cls.task_instance.has()(anti-join / NOT EXISTS semantics). - Add
SKIP LOCKEDrow locking to avoid concurrent triggerers contending for the same trigger rows during cleanup.
Uh oh!
There was an error while loading. Please reload this page.
hussein-awala
left a comment
There was a problem hiding this comment.
LGTM, I went through this carefully since it rewrites the delete predicate, and I'm satisfied it's a safe, well-motivated optimization.
For SKIP LOCKED: Good call for multi-triggerer, a single clean_unused() pass may now skip rows locked by a concurrent triggerer and leave them for the next run instead of always sweeping everything, which is the right trade-off.
ashb
left a comment
There was a problem hiding this comment.
Code looks okay, please update the PR title to say what it fixes/does, not what change it makes to the code.
(See the guide in our PT template on writing commit messages, that applies to PR title too.)
ab47768 to
f894790CompareAntonioBergonzi
commented
Jul 27, 2026
Good point! Done 😄 |
Uh oh!
There was an error while loading. Please reload this page.
Awesome work, congrats on your first merged pull request! You are invited to check our Issue Tracker for additional contributions. |
Backport successfully created: v3-3-testNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
|
hussein-awala
commented
Jul 29, 2026
Congrats @AntonioBergonzi on your first commit 🎉 |
…crashes (#68244) (#70668) * Use NOT EXISTS anti-join in Trigger.clean_unused instead of LEFT JOIN + aggregate * add FOR UPDATE SKIP LOCKED to Trigger.clean_unused to avoid deadlocks between concurrent triggerer pods * use with_row_locks helper and scope lock to trigger table (cherry picked from commit 2c1035a) Co-authored-by: AntonioBergonzi <48454032+AntonioBergonzi@users.noreply.github.com> Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
…crashes (#68244) (#70668) * Use NOT EXISTS anti-join in Trigger.clean_unused instead of LEFT JOIN + aggregate * add FOR UPDATE SKIP LOCKED to Trigger.clean_unused to avoid deadlocks between concurrent triggerer pods * use with_row_locks helper and scope lock to trigger table (cherry picked from commit 2c1035a) Co-authored-by: AntonioBergonzi <48454032+AntonioBergonzi@users.noreply.github.com> Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
…che#68244) * Use NOT EXISTS anti-join in Trigger.clean_unused instead of LEFT JOIN + aggregate * add FOR UPDATE SKIP LOCKED to Trigger.clean_unused to avoid deadlocks between concurrent triggerer pods * use with_row_locks helper and scope lock to trigger table
Description
Changed the query that checks for triggers that have no more callbacks, assets or task instances associated to them from count + aggregate to anti join on task_instance.
The result is the same (we are checking for non existence) but the query is more efficient. Also added skip locked since we run multiple triggerers and the different queries interfere with each other.
I did not add tests since I'm not introducing a new functionality, so the current one should cover the code change. If you think additional tests are needed, please let me know.
Testing
Plans of the queries
OLD QUERY:yields
NEW QUERY:
yields
Was generative AI tooling used to co-author this PR?
Claude Sonnet 1M
{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.