Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

BigQuery execute_sql blocks the event loop for the whole query

已关闭
#7,160 4 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 6 天内回复

@surajksharma07 已经在做这个了。

开始于 2026年9月17日。

评估

这个 Issue 还没有评估数据。

描述

request clarification tools

🔴 Required Information

Describe the Bug:
execute_sql in the BigQuery toolset is a plain def, and the BigQuery client it calls blocks (src/google/adk/integrations/bigquery/query_tool.py, L341 and the _execute_sql helper it delegates to at L169). ADK awaits a sync tool inline on the running loop, so nothing else in the process runs until the query comes back. On a server handling more than one session, the others just wait.

Spanner hit the same thing and was fixed in 1dbceccf. Bigtable's execute_sql is async too. BigQuery still has no asyncio.to_thread anywhere.

Steps to Reproduce:

  1. uv pip install "google-adk[gcp]==2.9.0"
  2. Save the script below (also under Minimal Reproduction Code) as repro.py. It replaces the BigQuery client with one that takes 2 seconds, so no credentials or real dataset are needed, and counts how many times a 100 ms heartbeat task gets to run during the query.
  3. python repro.py

Expected Behavior:
The heartbeat keeps ticking every 100 ms while the query is in flight.

Observed Behavior:
It doesn't tick at all until the query returns:

heartbeat ran 3 times
longest gap between heartbeats: 2.108s

The gap is the query duration.

Environment Details:

  • ADK Library Version (pip show google-adk): 2.9.0. Also checked main at 7ae1c9b0, still sync there.
  • Desktop OS: macOS 25.6.0 (arm64)
  • Python Version (python -V): 3.11.12, in a uv venv set up per the contribution guide (uv venv --python "python3.11" + uv sync --all-extras)

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A, no model involved

🟡 Optional Information

Regression:
No, it has always been sync.

Additional Context:
Same fix as Spanner: make execute_sql a coroutine and push _execute_sql into a thread. _execute_sql has to stay sync because forecast, analyze_contribution and detect_anomalies call it directly. Those three block the loop as well, but that's a separate change.

I have a patch and tests ready, so please assign this to me.

Minimal Reproduction Code:

import asyncio
import time
from unittest import mock

from google.adk.integrations.bigquery import query_tool
from google.adk.integrations.bigquery.config import BigQueryToolConfig
from google.adk.tools.tool_context import ToolContext
from google.auth.credentials import Credentials
from google.cloud import bigquery

QUERY_SECONDS = 2.0


async def heartbeat(stop):
    ticks = []
    start = time.monotonic()
    while not stop.is_set():
        await asyncio.sleep(0.1)
        ticks.append(time.monotonic() - start)
    return ticks


def slow_query_and_wait(*args, **kwargs):
    time.sleep(QUERY_SECONDS)
    return [{"num": 123}]


async def main():
    credentials = mock.create_autospec(Credentials, instance=True)
    tool_context = mock.create_autospec(ToolContext, instance=True)
    settings = BigQueryToolConfig()

    with mock.patch.object(bigquery, "Client", autospec=True) as client:
        bq_client = client.return_value
        query_job = mock.create_autospec(bigquery.QueryJob)
        query_job.statement_type = "SELECT"
        bq_client.query.return_value = query_job
        bq_client.query_and_wait.side_effect = slow_query_and_wait

        stop = asyncio.Event()
        beat = asyncio.create_task(heartbeat(stop))
        await asyncio.sleep(0.3)

        result = query_tool.execute_sql(
            "my_project", "SELECT 123 AS num", credentials, settings,
            tool_context,
        )
        if asyncio.iscoroutine(result):
            result = await result

        stop.set()
        ticks = await beat

    gaps = [b - a for a, b in zip(ticks, ticks[1:])]
    print(f"heartbeat ran {len(ticks)} times")
    print(f"longest gap between heartbeats: {max(gaps):.3f}s")
    print(f"result: {result}")


asyncio.run(main())

How often has this issue occurred?:

  • Always (100%)
主要语言
Python
星标
21.6k
派生
4k
平均合并
9 小时 59 分钟
30 天内合并 PR
5

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

google/adk-python 的其他 Issue

查看 google/adk-python 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。