4
4
from abc import ABC , abstractmethod
5
5
6
6
import google as google
7
+ import requests .exceptions
7
8
from google .api_core .exceptions import BadRequest , Forbidden
9
+ from google .api_core .retry import if_exception_type , if_transient_error
8
10
from google .cloud import bigquery
9
11
from google .cloud .bigquery .job import QueryJobConfig , CreateDisposition
10
12
from google .cloud .bigquery .schema import _parse_schema_resource
@@ -50,17 +52,28 @@ def delete_table(self, full_table_name):
50
52
def get_table (self , full_table_name ):
51
53
pass
52
54
55
+ def if_exception_funcs (fn_origin , fn_additional ):
56
+ def if_exception_func_predicate (exception ):
57
+ return fn_origin (exception ) or fn_additional (exception )
58
+ return if_exception_func_predicate
53
59
54
60
class BigqueryService (BaseBigqueryService ):
55
61
56
- def __init__ (self , client , labels , writer , on_job_finish = None , on_job_register = None ):
62
+ def __init__ (self , client , labels , writer , retry_timeout = None , on_job_finish = None , on_job_register = None ):
57
63
"""
58
64
59
65
:rtype:
60
66
"""
61
67
self .client = client
62
68
self .labels = labels
63
69
self .writer = writer
70
+ if_additional_transient_error = if_exception_type (
71
+ requests .exceptions .Timeout ,
72
+ requests .exceptions .SSLError ,
73
+ )
74
+ predicate = if_exception_funcs (if_transient_error , if_additional_transient_error )
75
+ retry = bigquery .DEFAULT_RETRY .with_deadline (retry_timeout ) if retry_timeout else bigquery .DEFAULT_RETRY
76
+ self .retry = retry .with_predicate (predicate )
64
77
self .on_job_finish = on_job_finish
65
78
self .on_job_register = on_job_register
66
79
@@ -74,7 +87,8 @@ def execute_query(self, query):
74
87
75
88
logger .info ("executing query" )
76
89
query_job = self .client .query (query = query ,
77
- job_config = query_job_config )
90
+ job_config = query_job_config ,
91
+ retry = self .retry )
78
92
logger .info ("Job {} is initially in state {} of {} project" .format (query_job .job_id , query_job .state ,
79
93
query_job .project ))
80
94
@@ -125,7 +139,9 @@ def transform_load(self,
125
139
query_job_config .destination = table_ref
126
140
127
141
logger .info ("transform load" )
128
- query_job = self .client .query (query = query , job_config = query_job_config )
142
+ query_job = self .client .query (query = query ,
143
+ job_config = query_job_config ,
144
+ retry = self .retry )
129
145
logger .info ("Job {} is initially in state {} of {} project" .format (query_job .job_id , query_job .state ,
130
146
query_job .project ))
131
147
@@ -183,7 +199,7 @@ def create_bigquery_service(task_config: TaskConfigFromEnv, labels, writer, on_j
183
199
default_query_job_config .priority = task_config .query_priority
184
200
default_query_job_config .allow_field_addition = task_config .allow_field_addition
185
201
client = bigquery .Client (project = task_config .execution_project , credentials = credentials , default_query_job_config = default_query_job_config )
186
- return BigqueryService (client , labels , writer , on_job_finish = on_job_finish , on_job_register = on_job_register )
202
+ return BigqueryService (client , labels , writer , retry_timeout = task_config . retry_timeout , on_job_finish = on_job_finish , on_job_register = on_job_register )
187
203
188
204
189
205
def _get_bigquery_credentials ():
0 commit comments