Make RedshiftDeleteClusterOperator delete reliably during cluster transitions#69574
Open
seanghaeli wants to merge 4 commits into
Open
Make RedshiftDeleteClusterOperator delete reliably during cluster transitions#69574seanghaeli wants to merge 4 commits into
seanghaeli wants to merge 4 commits into
Conversation
0f0e718 to
f442c94
Compare
added 4 commits
July 8, 2026 06:43
…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
vincbeck
reviewed
Jul 8, 2026
| if validated_event["status"] != "success": | ||
| raise AirflowException(f"Error waiting for cluster to become deletable: {validated_event}") | ||
|
|
||
| self._delete_or_defer_until_settled() |
Contributor
There was a problem hiding this comment.
This might not work if _retry_delete_when_settled is executed on a different machine/host than execute. If some random values are passed to the construct of RedshiftDeleteClusterOperator, then some values will differ between execute and _retry_delete_when_settled. For example, if a random number is used to define cluster_identifier, then definitely this will fail
Contributor
Author
There was a problem hiding this comment.
I believe the exact same pattern is used here in EKS:
I am going to investigate if this causes a fail but I think if this is an issue in this PR, it's also a latent issue in EKS currently
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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: