Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 46 additions & 24 deletions marketorestpython/helper/http_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
class HttpLib:
max_retries = 3
sleep_duration = 3
num_calls_per_second = 5 # can run five times per second at most (at 100/20 rate limit)

# run five times per second at most (at 100/20 rate limit)
num_calls_per_second = 5
def _rate_limited(maxPerSecond):
minInterval = 1.0 / float(maxPerSecond)
def decorate(func):
Expand Down Expand Up @@ -35,25 +35,35 @@ def get(self, endpoint, args=None, mode=None):
return r
else:
r_json = r.json()
# if we still hit the rate limiter, do not return anything so the call will be retried
if 'success' in r_json: # this is for all normal API calls (but not the access token call)
# if we still hit the rate limiter, do not return anything
# so the call will be retried
if 'success' in r_json:
# this is for normal API calls (not acccess token calls)
if r_json['success'] == False:
print('error from http_lib.py: ' + str(r_json['errors'][0]))
if r_json['errors'][0]['code'] in ('606', '615', '604'):
# this handles Marketo exceptions; HTTP response is still 200, but error is in the JSON
print('error from http_lib.py: {}'.format(
r_json['errors'][0]))
if r_json['errors'][0]['code'] in (
'606', '615', '604'):
# this handles Marketo exceptions; HTTP response
# is still 200, but error is in the JSON
error_code = r_json['errors'][0]['code']
error_description = {
'606': 'rate limiter',
'615': 'concurrent call limit',
'604': 'timeout'}
print('Attempt {}. Error {}, {}.'.format(
retries,
error_code,
error_description[error_code]))
if retries < self.max_retries:
print('Attempt %s. Error %s, %s. Pausing, then trying again.' % (retries, error_code, error_description[error_code]))
print('Pausing, then trying again.')
else:
print('Attempt %s. Error %s, %s. This was the final attempt.' % (retries, error_code, error_description[error_code]))
print('This was the final attempt.')
time.sleep(self.sleep_duration)
retries += 1
else:
# fatal exceptions will still error out; exceptions caught above may be recoverable
# fatal exceptions will still error out;
# exceptions caught above may be recoverable
return r_json
else:
return r_json
Expand All @@ -65,7 +75,8 @@ def get(self, endpoint, args=None, mode=None):
retries += 1

@_rate_limited(num_calls_per_second)
def post(self, endpoint, args, data=None, files=None, filename=None, mode=None):
def post(
self, endpoint, args, data=None, files=None, filename=None, mode=None):
retries = 1
while True:
if retries > self.max_retries:
Expand All @@ -75,33 +86,43 @@ def post(self, endpoint, args, data=None, files=None, filename=None, mode=None):
r = requests.post(endpoint, params=args, data=data)
elif files is None:
headers = {'Content-type': 'application/json'}
r = requests.post(endpoint, params=args, json=data, headers=headers)
r = requests.post(
endpoint, params=args, json=data, headers=headers)
elif files is not None:
mimetype = mimetypes.guess_type(files)[0]
file = {filename: (files, open(files, 'rb'), mimetype)}
r = requests.post(endpoint, params=args, json=data, files=file)
r = requests.post(
endpoint, params=args, json=data, files=file)
r_json = r.json()
# if we still hit the rate limiter, do not return anything so the call will be retried
if 'success' in r_json: # this is for all normal API calls (but not the access token call)
# if we still hit the rate limiter,
# do not return anything so the call will be retried
if 'success' in r_json:
# this is for normal API calls (not access token calls)
if r_json['success'] == False:
print('error from http_lib.py: ' + str(r_json['errors'][0]))
if r_json['errors'][0]['code'] in ('606', '615', '604'):
# this handles Marketo exceptions; HTTP response is still 200, but error is in the JSON
print('error from http_lib.py: {}'.format(
r_json['errors'][0]))
if r_json['errors'][0]['code'] in (
'606', '615', '604'):
# this handles Marketo exceptions; HTTP response is
# still 200, but error is in the JSON
error_code = r_json['errors'][0]['code']
error_description = {
'606': 'rate limiter',
'615': 'concurrent call limit',
'604': 'timeout'}
print('Attempt {}. Error {}, {}.'.format(
retries,
error_code,
error_description[error_code]))
if retries < self.max_retries:
print('Attempt %s. Error %s, %s. Pausing, then trying again.' % (
retries, error_code, error_description[error_code]))
print('Pausing, then trying again.')
else:
print('Attempt %s. Error %s, %s. This was the final attempt.' % (
retries, error_code, error_description[error_code]))
print('This was the final attempt.')
time.sleep(self.sleep_duration)
retries += 1
else:
# fatal exceptions will still error out; exceptions caught above may be recoverable
# fatal exceptions will still error out;
# exceptions caught above may be recoverable
return r_json
else:
return r_json
Expand All @@ -120,7 +141,8 @@ def delete(self, endpoint, args, data):
return None
try:
headers = {'Content-type': 'application/json'}
r = requests.delete(endpoint, params=args, json=data, headers=headers)
r = requests.delete(
endpoint, params=args, json=data, headers=headers)
return r.json()
except Exception as e:
print("HTTP Delete Exception! Retrying....."+ str(e))
Expand Down