Make RedshiftDeleteClusterOperator delete reliably during cluster transitions - #69574
Conversation
0f0e718 to
f442c94
Compare
…nsitions A delete issued while the cluster is mid-transition (pausing/resuming/resizing) raises InvalidClusterStateFault. The retry budget was hardcoded to 10 * 15s = 2.5 min, which expires long before a real transition settles (~minutes), so the task fails and the cluster leaks. Non-deferrable mode: raise the synchronous busy-retry budget to 60 * 15s = ~15 min so it outlasts a transition; still fail-loud once exhausted. Deferrable mode: previously the synchronous loop ran before the defer, blocking the worker. Now attempt the delete once; on InvalidClusterStateFault defer to a new RedshiftClusterSettledTrigger (an AwsBaseWaiterTrigger backed by a custom cluster_deletable waiter that treats transitional states as retry and fires once the cluster is deletable), then a callback re-issues the delete and defers to the existing RedshiftDeleteClusterTrigger; re-defers on a race. Bounded by the existing poll_interval/max_attempts. This mirrors the EKS deferrable re-defer pattern and the AwsBaseWaiterTrigger convention used by the other Redshift triggers. No worker is blocked in deferrable mode. Generated-by: Claude Code (Opus)
Comment-only: tighten the RedshiftClusterSettledTrigger class docstring and the _delete_or_defer_until_settled docstring, keeping the non-obvious rationale (multi-terminal-state -> custom waiter, which trigger handles which case). Generated-by: Claude Code (Opus)
Generated-by: Claude Code (Opus)
Generated-by: Claude Code (Opus)
f442c94 to
10122f7
Compare
|
@seanghaeli This PR has been converted to draft because it does not yet meet our Pull Request quality criteria. Issues found:
What to do next:
Converting a PR to draft is not a rejection — it is an invitation to bring the PR up to the project's standards so that maintainer review time is spent productively. There is no rush — take your time and work at your own pace. We appreciate your contribution and are happy to wait for updates. If you have questions, feel free to ask on the Airflow Slack. Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you. |
…lete-deferrable-wait # Conflicts: # docs/spelling_wordlist.txt
vincbeck
left a comment
There was a problem hiding this comment.
Thanks for doing the changes
…nsitions (apache#69574) A delete issued while the cluster is mid-transition (pausing/resuming/resizing) raises InvalidClusterStateFault. The retry budget was hardcoded to 10 * 15s = 2.5 min, which expires long before a real transition settles (~minutes), so the task fails and the cluster leaks. Non-deferrable mode: raise the synchronous busy-retry budget to 60 * 15s = ~15 min so it outlasts a transition; still fail-loud once exhausted. Deferrable mode: previously the synchronous loop ran before the defer, blocking the worker. Now attempt the delete once; on InvalidClusterStateFault defer to a new RedshiftClusterSettledTrigger (an AwsBaseWaiterTrigger backed by a custom cluster_deletable waiter that treats transitional states as retry and fires once the cluster is deletable), then a callback re-issues the delete and defers to the existing RedshiftDeleteClusterTrigger; re-defers on a race. Bounded by the existing poll_interval/max_attempts. This mirrors the EKS deferrable re-defer pattern and the AwsBaseWaiterTrigger convention used by the other Redshift triggers. No worker is blocked in deferrable mode.
Why
RedshiftDeleteClusterOperatorretries onInvalidClusterStateFaultwhen the cluster is mid-transition (pausing/resuming/resizing), but the retry budget was hardcoded to10 attempts * 15s = 2.5 minutes. Transitions routinely take longer, so the loop exhausts and re-raises before the cluster becomes deletable.The error seen mid-transition:
What
Non-deferrable mode: raise the synchronous busy-retry budget to
60 * 15s = ~15 minso it outlasts a transition. Still throw failure once timed out.Deferrable mode: previously the synchronous retry loop ran before the defer, blocking the worker for the whole budget (defeating the purpose of deferrable mode). Now the operator attempts the delete once; on
InvalidClusterStateFaultit defers to a newRedshiftClusterSettledTriggerthat treats transitional states as retry and fires once the cluster reaches a deletable lifecycle. A callback then re-issues the delete and defers to the existingRedshiftDeleteClusterTrigger(cluster_deleted); on a race it re-defers to the settle trigger. No worker is blocked at any point.Mirrors the deferrable re-defer pattern established for EKS in #32355
Testing
End-to-end before/after
Non-deferrable — BEFORE: FAILS, cluster leaks:
Non-deferrable — AFTER: SUCCEEDS, cluster deleted:
Deferrable — BEFORE: blocks worker 2.5 min then FAILS (never defers):
Deferrable — AFTER: async wait via
cluster_deletablewaiter, then delete. SUCCEEDS: