1818# under the License.
1919
2020# coding=utf-8
21+ import time
2122import warnings
2223import json
2324import aliyunsdkcore
3536
3637from aliyunsdkcore .endpoint .resolver_endpoint_request import ResolveEndpointRequest
3738from aliyunsdkcore .endpoint .default_endpoint_resolver import DefaultEndpointResolver
38-
39+ import aliyunsdkcore .retry .retry_policy as retry_policy
40+ from aliyunsdkcore .retry .retry_condition import RetryCondition
41+ from aliyunsdkcore .retry .retry_policy_context import RetryPolicyContext
3942
4043"""
4144Acs default client module.
@@ -52,7 +55,7 @@ def __init__(
5255 secret = None ,
5356 region_id = "cn-hangzhou" ,
5457 auto_retry = True ,
55- max_retry_time = 3 ,
58+ max_retry_time = None ,
5659 user_agent = None ,
5760 port = 80 ,
5861 timeout = DEFAULT_SDK_CONNECTION_TIMEOUT_IN_SECONDS ,
@@ -71,12 +74,12 @@ def __init__(
7174 :return:
7275 """
7376
74- self .__max_retry_num = max_retry_time
75- self .__auto_retry = auto_retry
76- self .__ak = ak
77- self .__secret = secret
78- self .__region_id = region_id
79- self .__user_agent = user_agent
77+ self ._max_retry_num = max_retry_time
78+ self ._auto_retry = auto_retry
79+ self ._ak = ak
80+ self ._secret = secret
81+ self ._region_id = region_id
82+ self ._user_agent = user_agent
8083 self ._port = port
8184 self ._timeout = timeout
8285 credential = {
@@ -91,6 +94,13 @@ def __init__(
9194 credential , region_id , self .implementation_of_do_action , debug )
9295 self ._endpoint_resolver = DefaultEndpointResolver (self )
9396
97+ if self ._auto_retry :
98+ self ._retry_policy = retry_policy .PREDEFINED_DEFAULT_RETRY_POLICY
99+ if self ._max_retry_num :
100+ self ._retry_policy .max_retry_times = self ._max_retry_num
101+ else :
102+ self ._retry_policy = retry_policy .NO_RETRY_POLICY
103+
94104 def get_region_id (self ):
95105 return self .__region_id
96106
@@ -189,12 +199,40 @@ def implementation_of_do_action(self, request, signer=None):
189199 else :
190200 endpoint = self ._resolve_endpoint (request )
191201
202+ return self ._handle_retry_and_timeout (endpoint , request , signer )
203+
204+ def _add_request_client_token (self , request ):
205+ if hasattr (request , "set_ClientToken" ):
206+
207+
208+ def _handle_retry_and_timeout (self , endpoint , request , signer ):
209+ # it's a temporary implement. the long-term plan will be a group a normalized handlers
210+ # which contains retry_handler and timeout_handler
211+ retryable = RetryCondition .SHOULD_RETRY
212+ retries = 0
213+ while retryable & RetryCondition .SHOULD_RETRY :
214+
215+ if retryable & RetryCondition .SHOULD_RETRY_WITH_CLIENT_TOKEN :
216+ self ._add_request_client_token (request )
217+
218+ status , headers , body , exception = self ._handle_single_request (endpoint ,
219+ request ,
220+ signer )
221+ retry_policy_context = RetryPolicyContext (request , exception , retries , status )
222+ retryable = self ._retry_policy .should_retry (retry_policy_context )
223+ retry_policy_context .retryable = retryable
224+ time_to_sleep = self ._retry_policy .compute_delay_before_next_retry (retry_policy_context )
225+ time .sleep (time_to_sleep / 1000.0 )
226+ retries += 1
227+
228+ def _handle_single_request (self , endpoint , request , signer ):
192229 http_response = self ._make_http_response (endpoint , request , signer )
193230
231+ exception = None
232+
194233 # Do the actual network thing
195234 try :
196235 status , headers , body = http_response .get_response_object ()
197- return status , headers , body
198236 except IOError as e :
199237 error_message = str (e )
200238 error_message += "\n Endpoint: " + endpoint
@@ -204,7 +242,11 @@ def implementation_of_do_action(self, request, signer=None):
204242 error_message += "\n HttpHeaders: " + \
205243 str (http_response .get_headers ())
206244
207- raise ClientException (error_code .SDK_HTTP_ERROR , error_message )
245+ exception = ClientException (error_code .SDK_HTTP_ERROR , error_message )
246+ return None , None , None , exception
247+
248+ exception = self ._get_server_exception (status , body )
249+ return status , headers , body , exception
208250
209251 @staticmethod
210252 def _parse_error_info_from_response_body (response_body ):
@@ -223,34 +265,38 @@ def _parse_error_info_from_response_body(response_body):
223265
224266 return error_code_to_return , error_message_to_return
225267
226- def do_action_with_exception (self , acs_request ):
227-
228- # set server response format as json, because this function will
229- # parse the response so which format doesn't matter
230- acs_request .set_accept_format ('JSON' )
231-
232- status , headers , body = self .implementation_of_do_action (acs_request )
233-
268+ def _get_server_exception (self , http_status , response_body ):
234269 request_id = None
235270
236271 try :
237- body_obj = json .loads (body .decode ('utf-8' ))
272+ body_obj = json .loads (response_body .decode ('utf-8' ))
238273 request_id = body_obj .get ('RequestId' )
239274 except (ValueError , TypeError , AttributeError ):
240275 # in case the response body is not a json string, return the raw
241276 # data instead
242277 pass
243278
244- if status < http_client .OK or status >= http_client .MULTIPLE_CHOICES :
279+ if http_status < http_client .OK or http_status >= http_client .MULTIPLE_CHOICES :
245280
246281 server_error_code , server_error_message = self ._parse_error_info_from_response_body (
247- body .decode ('utf-8' ))
248- raise ServerException (
282+ response_body .decode ('utf-8' ))
283+ return ServerException (
249284 server_error_code ,
250285 server_error_message ,
251- http_status = status ,
286+ http_status = http_status ,
252287 request_id = request_id )
253288
289+ def do_action_with_exception (self , acs_request ):
290+
291+ # set server response format as json, because this function will
292+ # parse the response so which format doesn't matter
293+ acs_request .set_accept_format ('JSON' )
294+
295+ status , headers , body , exception = self .implementation_of_do_action (acs_request )
296+
297+ if exception :
298+ raise exception
299+
254300 return body
255301
256302 def _resolve_endpoint (self , request ):
@@ -266,11 +312,12 @@ def do_action(self, acs_request):
266312 warnings .warn (
267313 "do_action() method is deprecated, please use do_action_with_exception() instead." ,
268314 DeprecationWarning )
269- status , headers , body = self .implementation_of_do_action (acs_request )
315+ status , headers , body , exception = self .implementation_of_do_action (acs_request )
270316 return body
271317
272318 def get_response (self , acs_request ):
273- return self .implementation_of_do_action (acs_request )
319+ status , headers , body , exception = self .implementation_of_do_action (acs_request )
320+ return status , headers , body
274321
275322 def add_endpoint (self , region_id , product_code , endpoint ):
276323 self ._endpoint_resolver .put_endpoint_entry (
0 commit comments