Repository navigation
Stop AWS Glue job run when a deferred task is cleared - #73702
Conversation
5d80206 to
2a321cd
Compare
seanghaeli
left a comment
There was a problem hiding this comment.
On my machine I'm seeing a problem arise with this PR when a deferred task is cleared. clear instructs the task to run again, and on 3.3+ the re-run looks for an existing Glue job from the same task. It finds the old one still running, and decides to just wait on that one. But clearing also triggers this PR's "on kill" step, which stops that same old Glue job. So the re-run ends up waiting on a stopped job and fails with STOPPED. On main, the re-run reattached and succeeded.
Could the re-run start a fresh Glue job when stop_job_run_on_kill=True, instead of reattaching?
68eedc3 to
db0041c
Compare
Thanks for reproducing this, you're right. on_kill fires on any user action and can't tell a clear from mark failed/success, so the re-run reattached to the run it was stopping. |
o-nikolas
left a comment
There was a problem hiding this comment.
With durable=False (or the deprecated resume_glue_job_on_retry=False), _build_script_args never adds --airflow_task_uuid, so script_args[self.TASK_UUID_ARG] raises KeyError on every retry. Could this condition also check self.durable? Without the tag the previous run can't be found anyway. A test for that combination would help too.
stop_job_run_on_kill was only honoured by the operator's synchronous on_kill, which never runs for a deferred task, so clearing, failing or succeeding a deferred Glue task left its job run going. The trigger's on_kill fires on every user action and cannot tell a clear, which re-runs the task, from mark failed or success. A cleared task's new try would otherwise reconnect (durable) to the run that on_kill is stopping and then fail on STOPPED. So when stop_job_run_on_kill is set, the retry stops the previous run itself and waits for it to end before submitting a new one: a STOPPING run still counts toward MaxConcurrentRuns, so submitting earlier would fail.
…thout durable Without durable the task UUID tag is never added to the job arguments, so the previous run cannot be found and every retry failed with a KeyError instead of starting a fresh run.
db0041c to
ff4f01f
Compare
Leondon9
left a comment
There was a problem hiding this comment.
Good catch, thanks. Added self.durable to the condition in ff4f01f, with a test for durable=False, stop_job_run_on_kill=True: no lookup, no stop, just a fresh submission. Without durable the trigger's on_kill still stops the old run, but the new submission can race it and hit ConcurrentRunsExceededException with MaxConcurrentRuns=1, as it does today. I noted that in the description.
This makes
GlueJobOperator'sstop_job_run_on_killwork on the deferrable path: when a deferred Glue task is cleared, marked failed or marked success, the Glue job run is stopped instead of being left running.Motivation
stop_job_run_on_killwas only honoured by the operator's synchronouson_kill, which does not run for a deferred task (the task lives in the triggerer, not on a worker). So a cleared deferrable Glue task left its job run going.EmrContainerTriggeralready stops its job fromon_kill(); this brings Glue in line.Behaviour
stop_job_run_on_kill=False).GlueJobCompleteTrigger.on_kill()stops the run. It uses the async client, so client creation stays off the triggerer event loop, and it logsbatch_stop_job_runErrorsinstead of ignoring them. Requires Airflow 3.3+, where the triggerer callsBaseTrigger.on_kill(); on older Airflow it is inert, same asEmrContainerTrigger.on_killfires on every user action and cannot tell a clear (which re-runs the task) from mark failed/success. Withdurableon (the 3.3+ default), the cleared task's new try would reconnect to the runon_killis stopping and then fail onSTOPPED. So whenstop_job_run_on_kill=Trueanddurable=Truein deferrable mode on 3.3+, a retried try stops the previous run itself, waits for it to reach a terminal state, then submits a new run. The wait matters because aSTOPPINGrun still counts towardMaxConcurrentRuns, so submitting earlier would hitConcurrentRunsExceededException.durablepath.GlueJobRunStopTimeoutErrorrather than starting a second run alongside it.durablethe job arguments carry no task UUID, so the previous run cannot be found; the retry submits a fresh run straight away and relies onon_killto stop the old one. WithMaxConcurrentRuns=1that submission can still hitConcurrentRunsExceededException, as it does today.durableand its default are untouched, andstop_job_run_on_kill=Falsekeeps the existing reconnect behaviour.on_kill()when a trigger is reassigned to another triggerer (fixed onmainin Skipon_kill()for triggers reassigned to another triggerer #73454). The docstring notes this.Synchronous mode is unchanged.
Testing
on_killstops the run when enabled, logs onErrors, and does nothing when disabled;stop_job_run_on_killserializes.STOPPING, and submits a fresh run, including whenon_killalready stopped it; the try fails without submitting if the run never stops; withoutdurablethe retry submits fresh without a lookup.prekpre-commit hooks and providermypy(breeze run mypy) on the changed files pass.amazon/aws-glue-libsimage does not provide Glue's control-plane API.Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Opus 4.8, Opus 5.5) following the guidelines
🤖 Generated with Claude Code