Skip to content

Cancel Snowflake queries when a user kills the deferred task - #69635

Open
steveahnahn wants to merge 3 commits into
apache:mainfrom
steveahnahn:snowflake-cancel-queries-on-user-kill-deferred
Open

Cancel Snowflake queries when a user kills the deferred task#69635
steveahnahn wants to merge 3 commits into
apache:mainfrom
steveahnahn:snowflake-cancel-queries-on-user-kill-deferred

Conversation

@steveahnahn

@steveahnahnsteveahnahn commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Problem

  • SnowflakeSqlApiOperator.on_kill cancels the running queries, but after defer() the worker is gone and it can never run.
  • SnowflakeSqlApiTrigger had no on_kill (base default is a no op), so killing a deferred task leaves the statements executing on the warehouse, burning credits.
  • Sibling triggers already cancel on user kill: EMR in the Amazon provider, BigQuery/Dataproc/Dataflow in the Google provider.

Change

  • Add on_kill to SnowflakeSqlApiTrigger: cancels the running query ids.
  • The SQL API cancel is a blocking POST with no async variant, so on_kill runs cancel_queries through sync_to_async, building the hook inside that worker so no connection work touches the event loop.
  • cancel_on_kill flag (default True) on operator and trigger; operator threads it into the trigger at the defer site.
  • Best effort: cancel failures are logged and swallowed. Fires only on user kill, never on triggerer restart, redistribution, or timeout.

Live verification

  1. Deferrable operator submitted a statement; task deferred, trigger polling (GET /api/v2/statements/{id} returning 202).

deferred task, trigger polling the statement

  1. Marked the task failed from the UI. Task log:
Trigger cancelled by user action, invoking on_kill
Cancelling Snowflake query ids ['069b68f4-8e5e-404a-aef9-0eca86eb396d']
Snowflake query ids ['069b68f4-8e5e-404a-aef9-0eca86eb396d'] cancelled

task failed, on_kill cancelling the Snowflake query

  1. The endpoint received POST /api/v2/statements/{id}/cancel and the statement transitioned to ABORTED. Without the change it stays running.

Tests

  • Trigger: cancel on kill, disabled/empty id no ops, error swallowing, serialization of the flag.
  • Operator: cancel_on_kill=False guard, flag threaded into the trigger on defer.
  • Every new assertion fails without the source change.

Was generative AI tooling used to co-author this PR?
  • Yes, Claude Code (Fable 5)

Generated-by: Claude Code (Fable 5) following the guidelines

@boring-cyborgboring-cyborgBot added area:providers provider:snowflake Issues related to Snowflake provider labels Jul 9, 2026
@steveahnahn
steveahnahnforce-pushed the snowflake-cancel-queries-on-user-kill-deferred branch from a7c612b to a878441CompareJuly 10, 2026 19:40
@steveahnahn
steveahnahn marked this pull request as ready for review July 10, 2026 22:57
@steveahnahn
steveahnahn requested a review from potiuk as a code ownerJuly 10, 2026 22:57
@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 11, 2026
@steveahnahn
steveahnahnforce-pushed the snowflake-cancel-queries-on-user-kill-deferred branch 2 times, most recently from 0bad94d to fbb14acCompareJuly 16, 2026 22:28

@potiukpotiuk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change — this closes a real gap, and threading cancel_on_kill through the defer site so the trigger inherits the operator's setting is the right shape.

I verified locally: the 57 trigger + operator tests pass, the async def on_kill signature matches BaseTrigger.on_kill (the triggerer awaits it, so a sync override would have silently never run), and the positional SnowflakeSqlApiHook(conn_id, token_life_time, token_renewal_delta) args match the constructor. Building the hook inside the sync_to_async worker rather than on the event loop is the correct call. Serialization round-trip coverage and the live-verification screenshots are appreciated.

One thing to fix and two I'd like your read on — left inline. Only the asgiref one is blocking.


Drafted-by: Claude Code (Opus 4.8); reviewed by @potiuk before posting

@steveahnahn
steveahnahnforce-pushed the snowflake-cancel-queries-on-user-kill-deferred branch 2 times, most recently from 50362e6 to 687272aCompareJuly 26, 2026 03:01
@github-actions

github-actionsBot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

uv.lock on main just moved via #72058 ("Fix linux/arm64 CI image build broken by the ibm.db2 provider"), commit 57a0519 and this PR currently conflicts.

Quickest fix:

git fetch upstream main && git rebase upstream/main
rm uv.lock && uv lock
git add uv.lock && git rebase --continue
git push --force-with-lease

Automated nudge — ignore if you're not ready to rebase. This comment is updated in place on future uv.lock bumps.

@steveahnahn
steveahnahnforce-pushed the snowflake-cancel-queries-on-user-kill-deferred branch 3 times, most recently from 8e02347 to bdd326cCompareAugust 8, 2026 00:32
A deferred SnowflakeSqlApiOperator parks its running query ids in the triggerer,
so the operator's own on_kill no longer runs once the task is deferred. When a
user marks that task failed, clears it, or marks it success, SnowflakeSqlApiTrigger
had no on_kill hook, so the Snowflake statements kept executing on the warehouse,
burning compute credits, even though the operator already cancels the queries on
kill in the non-deferred path.
This adds on_kill to SnowflakeSqlApiTrigger to cancel the running query ids when
the user acts on the deferred task, matching the behaviour already shipped for the
EMR, Dataproc, BigQuery, and Dataflow triggers. The Snowflake SQL API cancel is a
blocking POST with no async variant, so it runs through sync_to_async off the
triggerer event loop, and the hook is built inside that worker so no connection
work touches the loop. A cancel_on_kill flag on both the operator and the trigger
lets users opt out.
A single failing cancel (a reaped statement handle, a transient error)
would otherwise stop the remaining ids from being cancelled, leaving the
still-running statements that are actually consuming credits untouched.
Declare asgiref, which the trigger imports directly rather than relying
on it resolving transitively through apache-airflow.
@steveahnahn
steveahnahnforce-pushed the snowflake-cancel-queries-on-user-kill-deferred branch from bdd326c to 9c78611CompareAugust 17, 2026 00:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:snowflakeIssues related to Snowflake providerready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@steveahnahn@potiuk