def make_call(query, org_id, page):
wait_time = <NUM_LIT:0><EOL>num_attempts = <NUM_LIT:0><EOL>while num_attempts < retry_max_attempts:<EOL><INDENT>if wait_time > <NUM_LIT:0>:<EOL><INDENT>sleep(wait_time)<EOL>wait_time = <NUM_LIT:0><EOL><DEDENT>try:<EOL><INDENT>num_attempts += <NUM_LIT:1><EOL>return query(org_id, page)<EOL><DEDENT>except UMAPIRetryError as e:<EOL><INDENT>logger.warning("<STR_LIT>", num_attempts, e.res.status_code)<EOL>if "<STR_LIT>" in e.res.headers:<EOL><INDENT>advice = e.res.headers["<STR_LIT>"]<EOL>advised_time = parsedate_tz(advice)<EOL>if advised_time is not None:<EOL><INDENT>wait_time = int(mktime_tz(advised_time) - time())<EOL><DEDENT>else:<EOL><INDENT>wait_time = int(advice)<EOL><DEDENT><DEDENT>if wait_time <= <NUM_LIT:0>:<EOL><INDENT>delay = randint(<NUM_LIT:0>, retry_random_delay_max)<EOL>wait_time = (int(pow(<NUM_LIT:2>, num_attempts)) * retry_exponential_backoff_factor) + delay<EOL><DEDENT>logger.warning("<STR_LIT>", wait_time)<EOL>continue<EOL><DEDENT>except UMAPIRequestError as e:<EOL><INDENT>logger.warning("<STR_LIT>", e.code)<EOL>return {}<EOL><DEDENT>except UMAPIError as e:<EOL><INDENT>logger.warning("<STR_LIT>", e.res.status_code, e.res.text)<EOL>return {}<EOL><DEDENT><DEDENT>logger.error("<STR_LIT>", page, retry_max_attempts)<EOL>return {}<EOL>
Make a single UMAPI call with error handling and server-controlled throttling.
(Adapted from sample code at https://www.adobe.io/products/usermanagement/docs/samples#retry)
:param query: a query method from a UMAPI instance (callable as a function)
:param org_id: the organization being queried
:param page: the page number of the desired result set
:return: the json (dictionary) received from the server (if any)