Skip to content

Databricks: resolve connection asynchronously in trigger to prevent A… - #72245

Open
aman-pathak1 wants to merge 2 commits into
apache:mainfrom
aman-pathak1:fix-databricks-trigger-asynctosync-71525
Open

Databricks: resolve connection asynchronously in trigger to prevent A…#72245
aman-pathak1 wants to merge 2 commits into
apache:mainfrom
aman-pathak1:fix-databricks-trigger-asynctosync-71525

Conversation

@aman-pathak1

Copy link
Copy Markdown

…syncToSync failure (#71525)


Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

Copilot AI lite review requested due to automatic review settings August 29, 2026 06:26
@boring-cyborg

boring-cyborg Bot commented Aug 29, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
Here are some useful points:

  • Pay attention to the quality of your code (ruff, mypy and type annotations). Our prek-hooks will help you with that.
  • In case of a new feature add useful documentation (in docstrings or in docs/ directory). Adding a new operator? Check this short guide Consider adding an example Dag that shows how users should use it.
  • Consider using Breeze environment for testing locally, it's a heavy docker but it ships with a working Airflow and a lot of integrations.
  • Be patient and persistent. It might take some time to get a review or get the final approval from Committers.
  • Please follow ASF Code of Conduct for all communication including (but not limited to) comments on Pull Requests, Mailing list and Slack.
  • Be sure to read the Airflow Coding style.
  • Always keep your Pull Requests rebased, otherwise your build might fail due to changes not related to your commits.
    Apache Airflow is a community-driven project and together we are making it better 🚀.
    In case of doubts contact the developers at:
    Mailing List: dev@airflow.apache.org
    Slack: https://s.apache.org/airflow-slack

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses #71525 by making Databricks deferrable trigger execution avoid sync connection resolution inside an active asyncio event loop (the AsyncToSync failure path), by introducing/using async-safe connection lookup and async hook methods in trigger code paths.

Changes:

  • Add an async-safe connection resolution method to BaseDatabricksHook and ensure async API calls pre-resolve/cache the connection.
  • Replace sync_to_async(...) wrappers in Databricks triggers with native async hook methods.
  • Add async hook methods for run-task pagination and cancellation operations used by triggers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
providers/databricks/src/airflow/providers/databricks/triggers/databricks.py Switch trigger cancellation/status paths from sync_to_async-wrapped sync hook calls to native async hook methods.
providers/databricks/src/airflow/providers/databricks/hooks/databricks.py Add async variants for run-task retrieval and cancellation APIs so trigger code can stay fully async.
providers/databricks/src/airflow/providers/databricks/hooks/databricks_base.py Add async-safe connection lookup/caching and ensure async request/token helpers pre-resolve the connection to avoid sync lookup inside the event loop.
Suppressed comments (1)

providers/databricks/src/airflow/providers/databricks/triggers/databricks.py:289

  • on_kill() calls a_cancel_sql_statement(), which uses _a_do_api_call() and therefore requires an aiohttp session from async with self.hook. The triggerer calls on_kill() after cancelling run() (after the async with self.hook in run() has unwound), so _session may be None here and cancellation can crash instead of best-effort cancelling.

Wrap the cancellation logic in async with self.hook: (and adjust unit tests that currently patch cancel_sql_statement to patch a_cancel_sql_statement).

    async def on_kill(self) -> None:
        """Cancel the Databricks SQL statement when the trigger is cancelled by a user action."""
        if self.statement_id:
            self.log.info("Cancelling Databricks SQL statement %s.", self.statement_id)
            await self.hook.a_cancel_sql_statement(self.statement_id)

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 109 to 113
async def on_kill(self) -> None:
"""Cancel the Databricks run when the trigger is cancelled by a user action."""
from asgiref.sync import sync_to_async

run_id = self.run_id
if self.workflow_run_id is not None and self.databricks_task_key is not None:
# self.run_id may be an earlier, now-terminal attempt; cancel the task's latest attempt
Comment on lines +607 to +630
async def a_get_run_tasks(self, run_id: int) -> list[dict[str, Any]]:
"""
Retrieve list of tasks performed by the run (async version).

:param run_id: id of the run
:return: A list of tasks
"""
has_more = True
all_tasks = []
page_token = ""
json: dict[str, Any] = {"run_id": run_id}

while has_more:
if page_token:
json = {**json, "page_token": page_token}
response = await self._a_do_api_call(GET_RUN_ENDPOINT, json)
tasks = response.get("tasks", [])
all_tasks += tasks
if "next_page_token" in response:
page_token = response["next_page_token"]
else:
has_more = False

return all_tasks

@justinpakzad justinpakzad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the PR. It seems the title got cut off and there is no description. Can you please fix the title and add a description.

@aman-pathak1

Copy link
Copy Markdown
Author

Thanks for the PR. It seems the title got cut off and there is no description. Can you please fix the title and add a description.

ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants