Repository navigation
Batch triggerer unused trigger cleanup deletes - #70961
Conversation
eb1f434 to
f1157d6
Compare
Large trigger tables make synchronous cleanup hold locks until every eligible row is deleted, delaying triggerer progress and database writers.
A large cleanup backlog must not keep the triggerer supervisor away from runner communication, heartbeat, and metrics work.
f1157d6 to
f798a39
Compare
|
Cross-reference: #74650 is a minimal, targeted fix for #74614 (triggerer exiting with The restructure in this PR — moving the retry around a Drafted-by: Claude Code (Opus 4.7) (human reviewed before posting) |
|
Both points from the last round are in: the DELETE re-checks all three referrers, and each Two non-blocking notes:
|
Backport successfully created: v3-4-testNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
|
…74950) * Batch triggerer unused trigger cleanup deletes Large trigger tables make synchronous cleanup hold locks until every eligible row is deleted, delaying triggerer progress and database writers. * Add unreferenced to spelling wordlist * Protect re-referenced triggers during cleanup * Yield between unused-trigger cleanup batches A large cleanup backlog must not keep the triggerer supervisor away from runner communication, heartbeat, and metrics work. * Clarify unused-trigger batch behavior (cherry picked from commit c3cc557) Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Restore the keyword-only session argument that apache#70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction. Co-Authored-By: Claude <noreply@anthropic.com>
Restore the keyword-only session argument that apache#70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction.
Restore the keyword-only session argument that #70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction.
…ssion (apache#75096) Restore the keyword-only session argument that apache#70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction. (cherry picked from commit e3110a3) Co-authored-by: Kaxil Naik <kaxilnaik@gmail.com>
…ssion (apache#75096) Restore the keyword-only session argument that apache#70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction. (cherry picked from commit e3110a3) Co-authored-by: Kaxil Naik <kaxilnaik@gmail.com>
…ssion (#75096) (#75122) Restore the keyword-only session argument that #70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction. (cherry picked from commit e3110a3) Co-authored-by: Kaxil Naik <kaxilnaik@gmail.com>
…74950) * Batch triggerer unused trigger cleanup deletes Large trigger tables make synchronous cleanup hold locks until every eligible row is deleted, delaying triggerer progress and database writers. * Add unreferenced to spelling wordlist * Protect re-referenced triggers during cleanup * Yield between unused-trigger cleanup batches A large cleanup backlog must not keep the triggerer supervisor away from runner communication, heartbeat, and metrics work. * Clarify unused-trigger batch behavior (cherry picked from commit c3cc557) Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
…ssion (#75096) (#75122) Restore the keyword-only session argument that #70961 removed, so callers that run the cleanup inside their own transaction keep working. The model method now deletes one batch in the caller's transaction without retrying: a retry would have to roll back that transaction and silently discard the caller's other writes. The triggerer supervisor owns the retry instead and runs each attempt in a new transaction. (cherry picked from commit e3110a3) Co-authored-by: Kaxil Naik <kaxilnaik@gmail.com>
* Batch triggerer unused trigger cleanup deletes Large trigger tables make synchronous cleanup hold locks until every eligible row is deleted, delaying triggerer progress and database writers. * Add unreferenced to spelling wordlist * Protect re-referenced triggers during cleanup * Yield between unused-trigger cleanup batches A large cleanup backlog must not keep the triggerer supervisor away from runner communication, heartbeat, and metrics work. * Clarify unused-trigger batch behavior
Trigger.clean_unused()runs synchronously in every triggerer supervisor loop. It previously removed every eligible trigger in one transaction, so large cleanups could hold many row locks and delay the triggerer heartbeat and concurrent database work.This change deletes at most one configured batch of unreferenced triggers per triggerer loop and database transaction. Remaining triggers are handled in later loops, allowing the triggerer to resume runner servicing and heartbeat between batches.
The cleanup:
SKIP LOCKEDso concurrent triggerers can select different rows.DELETEbefore removing a trigger.Tests cover empty, below-limit, exact-limit, and larger-than-limit backlogs; draining five rows across three calls (
2,2,1); protected task, asset, and callback references; invalid configuration; and fresh retry transactions.Trade-off
Cleanup no longer drains the complete backlog in one call. Remaining rows wait for later triggerer loops. The batch size can be increased when necessary, with the trade-off that larger batches create larger transactions and may hold more database locks.
Follow-ups
callback.trigger_idstill needs a portable index and Alembic migration. That database change is intentionally kept separate from this focused cleanup change.Prior work: #68269 proposed the original batching direction. This implementation is a current-main rewrite because that draft predates #68244 and committed inside a caller-injected session.
Validation:
[500, 500].upstream/mainatd0b8476825; all five contribution commits remained exact range-diff matches.closes: #68243
Was generative AI tooling used to co-author this PR?
Generated-by: Codex (GPT-5) following the guidelines