From 340ba1b2206b87a374f1b0a112b66078517c214f Mon Sep 17 00:00:00 2001 From: "Slai.life" Date: Thu, 29 Oct 2026 03:50:38 +0800 Subject: [PATCH] fix(bigquery): default query results polling timeout --- .../google/cloud/bigquery/job/query.py | 19 ++++----- .../tests/unit/job/test_query.py | 40 ++++++++++++++++--- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/packages/google-cloud-bigquery/google/cloud/bigquery/job/query.py b/packages/google-cloud-bigquery/google/cloud/bigquery/job/query.py index 0b7af6293851..a93f5c31a6d6 100644 --- a/packages/google-cloud-bigquery/google/cloud/bigquery/job/query.py +++ b/packages/google-cloud-bigquery/google/cloud/bigquery/job/query.py @@ -42,6 +42,7 @@ ) from google.cloud.bigquery.retry import ( DEFAULT_RETRY, + DEFAULT_GET_JOB_TIMEOUT, DEFAULT_JOB_RETRY, POLLING_DEFAULT_VALUE, ) @@ -1498,7 +1499,7 @@ def _begin(self, client=None, retry=DEFAULT_RETRY, timeout=None): def _reload_query_results( self, retry: "retries.Retry" = DEFAULT_RETRY, - timeout: Optional[float] = None, + timeout: Optional[Union[float, object]] = POLLING_DEFAULT_VALUE, page_size: int = 0, start_index: Optional[int] = None, ): @@ -1544,16 +1545,16 @@ def _reload_query_results( self._done_timeout = max(0, self._done_timeout) timeout_ms = int(api_timeout * 1000) - # If an explicit timeout is not given, fall back to the transport timeout - # stored in _blocking_poll() in the process of polling for job completion. - if timeout is not None: - transport_timeout = timeout - else: + if timeout is POLLING_DEFAULT_VALUE: + # Fall back to the transport timeout stored in _blocking_poll() + # while polling for job completion. If no transport timeout was + # provided, use the same default as jobs.get. transport_timeout = self._transport_timeout - - # Handle PollingJob._DEFAULT_VALUE. if not isinstance(transport_timeout, (float, int)): - transport_timeout = None + transport_timeout = DEFAULT_GET_JOB_TIMEOUT + else: + # An explicit None keeps the request unbounded. + transport_timeout = timeout self._query_results = self._client._get_query_results( self.job_id, diff --git a/packages/google-cloud-bigquery/tests/unit/job/test_query.py b/packages/google-cloud-bigquery/tests/unit/job/test_query.py index daa3d4bd4dc7..452fccad08aa 100644 --- a/packages/google-cloud-bigquery/tests/unit/job/test_query.py +++ b/packages/google-cloud-bigquery/tests/unit/job/test_query.py @@ -920,6 +920,36 @@ def test_reload_query_results_uses_transport_timeout(self): timeout=123, ) + def test_reload_query_results_uses_default_timeout(self): + conn = make_connection({}) + client = _make_client(self.PROJECT, connection=conn) + job = self._make_one(self.JOB_ID, self.QUERY, client) + + job._reload_query_results() + + query_results_path = f"/projects/{self.PROJECT}/queries/{self.JOB_ID}" + conn.api_request.assert_called_once_with( + method="GET", + path=query_results_path, + query_params={"maxResults": 0}, + timeout=DEFAULT_GET_JOB_TIMEOUT, + ) + + def test_reload_query_results_with_none_timeout(self): + conn = make_connection({}) + client = _make_client(self.PROJECT, connection=conn) + job = self._make_one(self.JOB_ID, self.QUERY, client) + + job._reload_query_results(timeout=None) + + query_results_path = f"/projects/{self.PROJECT}/queries/{self.JOB_ID}" + conn.api_request.assert_called_once_with( + method="GET", + path=query_results_path, + query_params={"maxResults": 0}, + timeout=None, + ) + def test_result_reloads_job_state_until_done(self): """Verify that result() doesn't return until state == 'DONE'. @@ -1045,7 +1075,7 @@ def test_result_reloads_job_state_until_done(self): method="GET", path=query_results_path, query_params={"maxResults": 0, "location": "EU"}, - timeout=None, + timeout=DEFAULT_GET_JOB_TIMEOUT, ) reload_call = mock.call( method="GET", @@ -1176,7 +1206,7 @@ def test_result_begin_job_if_not_exist(self): "maxResults": 0, "location": "US", }, - timeout=None, + timeout=DEFAULT_GET_JOB_TIMEOUT, ) connection.api_request.assert_has_calls( @@ -1223,7 +1253,7 @@ def test_result_with_done_job_calls_get_query_results(self): method="GET", path=query_results_path, query_params={"maxResults": 0, "location": "EU"}, - timeout=None, + timeout=DEFAULT_GET_JOB_TIMEOUT, ) query_results_page_call = mock.call( method="GET", @@ -1411,7 +1441,7 @@ def test_result_with_max_results(self): "formatOptions.useInt64Timestamp": True, "location": "US", }, - timeout=None, + timeout=DEFAULT_GET_JOB_TIMEOUT, ) query_page_2_call = mock.call( timeout=None, @@ -1525,7 +1555,7 @@ def test_result_w_page_size(self): "location": "US", "formatOptions.useInt64Timestamp": True, }, - timeout=None, + timeout=DEFAULT_GET_JOB_TIMEOUT, ) query_page_2_call = mock.call( timeout=None,