From 44c6cfde4ef97181681b268b21ceab1b0c5ad0a5 Mon Sep 17 00:00:00 2001 From: Renan Butkeraites Date: Thu, 24 Oct 2024 16:32:02 -0300 Subject: [PATCH] Add backoff handling more errors (#18) --- src/tap_intacct/client.py | 56 ++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/tap_intacct/client.py b/src/tap_intacct/client.py index 5205441..d1e8d4c 100644 --- a/src/tap_intacct/client.py +++ b/src/tap_intacct/client.py @@ -29,6 +29,8 @@ AuthFailure ) +from http.client import RemoteDisconnected + class PleaseTryAgainLaterError(Exception): pass @@ -36,6 +38,15 @@ class PleaseTryAgainLaterError(Exception): logger = singer.get_logger() +class InvalidXmlResponse(Exception): + pass +class BadGatewayError(Exception): + pass +class OfflineServiceError(Exception): + pass +class RateLimitError(Exception): + pass + def _format_date_for_intacct(datetime: dt.datetime) -> str: """ Intacct expects datetimes in a 'MM/DD/YY HH:MM:SS' string format. @@ -128,11 +139,22 @@ def _set_session_id(self, user_id: str, company_id: str, user_password: str): else: raise SageIntacctSDKError('Error: {0}'.format(response['errormessage'])) + @backoff.on_exception( + backoff.expo, + ( + BadGatewayError, + OfflineServiceError, + ConnectionError, + ConnectionResetError, + requests.exceptions.ConnectionError, + InternalServerError, + RateLimitError, + RemoteDisconnected, + ), + max_tries=8, + factor=3, + ) @singer.utils.ratelimit(10, 1) - @backoff.on_exception(backoff.expo, - (ExpatError, PleaseTryAgainLaterError), - max_tries=5, - factor=2) def _post_request(self, dict_body: dict, api_url: str) -> Dict: """ Create a HTTP post request. @@ -148,10 +170,31 @@ def _post_request(self, dict_body: dict, api_url: str) -> Dict: api_headers = {'content-type': 'application/xml'} api_headers.update(self.__headers) body = xmltodict.unparse(dict_body) + logger.info(f"request to {api_url} with body {body}") response = requests.post(api_url, headers=api_headers, data=body) - parsed_xml = xmltodict.parse(response.text) - parsed_response = json.loads(json.dumps(parsed_xml)) + logger.info( + f"request to {api_url} response {response.text}, statuscode {response.status_code}" + ) + try: + parsed_xml = xmltodict.parse(response.text) + parsed_response = json.loads(json.dumps(parsed_xml)) + except: + if response.status_code == 502: + raise BadGatewayError( + f"Response status code: {response.status_code}, response: {response.text}" + ) + if response.status_code == 503: + raise OfflineServiceError( + f"Response status code: {response.status_code}, response: {response.text}" + ) + if response.status_code == 429: + raise RateLimitError( + f"Response status code: {response.status_code}, response: {response.text}" + ) + raise InvalidXmlResponse( + f"Response status code: {response.status_code}, response: {response.text}" + ) if response.status_code == 200: if parsed_response['response']['control']['status'] == 'success': @@ -453,3 +496,4 @@ def get_client( ) return connection +