26
26
from six .moves import http_client
27
27
28
28
import google .api_core .future .polling
29
- from google .auth .transport .requests import TimeoutGuard
30
29
from google .cloud import exceptions
31
30
from google .cloud .exceptions import NotFound
32
31
from google .cloud .bigquery .dataset import Dataset
55
54
_DONE_STATE = "DONE"
56
55
_STOPPED_REASON = "stopped"
57
56
_TIMEOUT_BUFFER_SECS = 0.1
58
- _SERVER_TIMEOUT_MARGIN_SECS = 1.0
59
57
_CONTAINS_ORDER_BY = re .compile (r"ORDER\s+BY" , re .IGNORECASE )
60
58
61
59
_ERROR_REASON_TO_EXCEPTION = {
@@ -796,8 +794,8 @@ def result(self, retry=DEFAULT_RETRY, timeout=None):
796
794
timeout (Optional[float]):
797
795
The number of seconds to wait for the underlying HTTP transport
798
796
before using ``retry``.
799
- If multiple requests are made under the hood, ``timeout`` is
800
- interpreted as the approximate total time of **all** requests .
797
+ If multiple requests are made under the hood, ``timeout``
798
+ applies to each individual request .
801
799
802
800
Returns:
803
801
_AsyncJob: This instance.
@@ -809,11 +807,7 @@ def result(self, retry=DEFAULT_RETRY, timeout=None):
809
807
if the job did not complete in the given timeout.
810
808
"""
811
809
if self .state is None :
812
- with TimeoutGuard (
813
- timeout , timeout_error_type = concurrent .futures .TimeoutError
814
- ) as guard :
815
- self ._begin (retry = retry , timeout = timeout )
816
- timeout = guard .remaining_timeout
810
+ self ._begin (retry = retry , timeout = timeout )
817
811
# TODO: modify PollingFuture so it can pass a retry argument to done().
818
812
return super (_AsyncJob , self ).result (timeout = timeout )
819
813
@@ -2602,6 +2596,7 @@ def __init__(self, job_id, query, client, job_config=None):
2602
2596
self ._configuration = job_config
2603
2597
self ._query_results = None
2604
2598
self ._done_timeout = None
2599
+ self ._transport_timeout = None
2605
2600
2606
2601
@property
2607
2602
def allow_large_results (self ):
@@ -3059,19 +3054,9 @@ def done(self, retry=DEFAULT_RETRY, timeout=None):
3059
3054
self ._done_timeout = max (0 , self ._done_timeout )
3060
3055
timeout_ms = int (api_timeout * 1000 )
3061
3056
3062
- # If the server-side processing timeout (timeout_ms) is specified and
3063
- # would be picked as the total request timeout, we want to add a small
3064
- # margin to it - we don't want to timeout the connection just as the
3065
- # server-side processing might have completed, but instead slightly
3066
- # after the server-side deadline.
3067
- # However, if `timeout` is specified, and is shorter than the adjusted
3068
- # server timeout, the former prevails.
3069
- if timeout_ms is not None and timeout_ms > 0 :
3070
- server_timeout_with_margin = timeout_ms / 1000 + _SERVER_TIMEOUT_MARGIN_SECS
3071
- if timeout is not None :
3072
- timeout = min (server_timeout_with_margin , timeout )
3073
- else :
3074
- timeout = server_timeout_with_margin
3057
+ # If an explicit timeout is not given, fall back to the transport timeout
3058
+ # stored in _blocking_poll() in the process of polling for job completion.
3059
+ transport_timeout = timeout if timeout is not None else self ._transport_timeout
3075
3060
3076
3061
# Do not refresh if the state is already done, as the job will not
3077
3062
# change once complete.
@@ -3082,19 +3067,20 @@ def done(self, retry=DEFAULT_RETRY, timeout=None):
3082
3067
project = self .project ,
3083
3068
timeout_ms = timeout_ms ,
3084
3069
location = self .location ,
3085
- timeout = timeout ,
3070
+ timeout = transport_timeout ,
3086
3071
)
3087
3072
3088
3073
# Only reload the job once we know the query is complete.
3089
3074
# This will ensure that fields such as the destination table are
3090
3075
# correctly populated.
3091
3076
if self ._query_results .complete :
3092
- self .reload (retry = retry , timeout = timeout )
3077
+ self .reload (retry = retry , timeout = transport_timeout )
3093
3078
3094
3079
return self .state == _DONE_STATE
3095
3080
3096
3081
def _blocking_poll (self , timeout = None ):
3097
3082
self ._done_timeout = timeout
3083
+ self ._transport_timeout = timeout
3098
3084
super (QueryJob , self )._blocking_poll (timeout = timeout )
3099
3085
3100
3086
@staticmethod
@@ -3170,8 +3156,8 @@ def result(
3170
3156
timeout (Optional[float]):
3171
3157
The number of seconds to wait for the underlying HTTP transport
3172
3158
before using ``retry``.
3173
- If multiple requests are made under the hood, ``timeout`` is
3174
- interpreted as the approximate total time of **all** requests .
3159
+ If multiple requests are made under the hood, ``timeout``
3160
+ applies to each individual request .
3175
3161
3176
3162
Returns:
3177
3163
google.cloud.bigquery.table.RowIterator:
@@ -3189,27 +3175,17 @@ def result(
3189
3175
If the job did not complete in the given timeout.
3190
3176
"""
3191
3177
try :
3192
- guard = TimeoutGuard (
3193
- timeout , timeout_error_type = concurrent .futures .TimeoutError
3194
- )
3195
- with guard :
3196
- super (QueryJob , self ).result (retry = retry , timeout = timeout )
3197
- timeout = guard .remaining_timeout
3178
+ super (QueryJob , self ).result (retry = retry , timeout = timeout )
3198
3179
3199
3180
# Return an iterator instead of returning the job.
3200
3181
if not self ._query_results :
3201
- guard = TimeoutGuard (
3202
- timeout , timeout_error_type = concurrent .futures .TimeoutError
3182
+ self ._query_results = self ._client ._get_query_results (
3183
+ self .job_id ,
3184
+ retry ,
3185
+ project = self .project ,
3186
+ location = self .location ,
3187
+ timeout = timeout ,
3203
3188
)
3204
- with guard :
3205
- self ._query_results = self ._client ._get_query_results (
3206
- self .job_id ,
3207
- retry ,
3208
- project = self .project ,
3209
- location = self .location ,
3210
- timeout = timeout ,
3211
- )
3212
- timeout = guard .remaining_timeout
3213
3189
except exceptions .GoogleCloudError as exc :
3214
3190
exc .message += self ._format_for_exception (self .query , self .job_id )
3215
3191
exc .query_job = self
0 commit comments