|
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | 15 | import os |
| 16 | +import random |
| 17 | +import time |
| 18 | + |
| 19 | +import requests |
16 | 20 |
|
17 | 21 | from veadk.auth.veauth.utils import get_credential_from_vefaas_iam |
18 | 22 | from veadk.utils.logger import get_logger |
|
25 | 29 | # name or exhaust the list. |
26 | 30 | _ARK_PROJECT_NAME = "default" |
27 | 31 | _ARK_PAGE_SIZE = 100 |
| 32 | +_RAW_API_KEY_MAX_ATTEMPTS = 3 |
| 33 | +_RAW_API_KEY_RETRY_DELAYS_SECONDS = (0.2, 0.5) |
| 34 | +_RAW_API_KEY_RETRYABLE_ERROR_CODES = { |
| 35 | + "InternalError", |
| 36 | + "InternalServiceTimeout", |
| 37 | + "RequestTimeout", |
| 38 | + "ServiceUnavailable", |
| 39 | + "Throttling", |
| 40 | + "TooManyRequests", |
| 41 | +} |
| 42 | +_RAW_API_KEY_RETRYABLE_ERROR_CODE_NUMBERS = {100016} |
| 43 | + |
| 44 | + |
| 45 | +def _response_error(res: dict) -> dict: |
| 46 | + metadata = res.get("ResponseMetadata", {}) |
| 47 | + if not isinstance(metadata, dict): |
| 48 | + return {} |
| 49 | + error = metadata.get("Error", {}) |
| 50 | + return error if isinstance(error, dict) else {} |
| 51 | + |
| 52 | + |
| 53 | +def _is_retryable_raw_api_key_response(res: dict) -> bool: |
| 54 | + error = _response_error(res) |
| 55 | + return ( |
| 56 | + error.get("Code") in _RAW_API_KEY_RETRYABLE_ERROR_CODES |
| 57 | + or error.get("CodeN") in _RAW_API_KEY_RETRYABLE_ERROR_CODE_NUMBERS |
| 58 | + ) |
| 59 | + |
| 60 | + |
| 61 | +def _sleep_before_raw_api_key_retry(attempt: int) -> None: |
| 62 | + delay = _RAW_API_KEY_RETRY_DELAYS_SECONDS[ |
| 63 | + min(attempt - 1, len(_RAW_API_KEY_RETRY_DELAYS_SECONDS) - 1) |
| 64 | + ] |
| 65 | + time.sleep(delay + random.uniform(0, delay / 5)) |
28 | 66 |
|
29 | 67 |
|
30 | 68 | def get_ark_token( |
@@ -142,20 +180,46 @@ def _list_api_keys(page_number: int) -> dict: |
142 | 180 | if isinstance(target_id, str) and target_id.isdigit() |
143 | 181 | else target_id |
144 | 182 | ) |
145 | | - res = ve_request( |
146 | | - request_body={"Id": request_key_id, "ProjectName": _ARK_PROJECT_NAME}, |
147 | | - header={"X-Security-Token": session_token}, |
148 | | - action="GetRawApiKey", |
149 | | - ak=access_key, |
150 | | - sk=secret_key, |
151 | | - service="ark", |
152 | | - version="2024-01-01", |
153 | | - region=region, |
154 | | - host=host, |
155 | | - ) |
156 | | - try: |
157 | | - api_key = res["Result"]["ApiKey"] |
158 | | - logger.info("Successfully fetched ARK API Key.") |
159 | | - return api_key |
160 | | - except KeyError as error: |
161 | | - raise ValueError("Failed to get ARK API key.") from error |
| 183 | + request_body = {"Id": request_key_id, "ProjectName": _ARK_PROJECT_NAME} |
| 184 | + for attempt in range(1, _RAW_API_KEY_MAX_ATTEMPTS + 1): |
| 185 | + try: |
| 186 | + res = ve_request( |
| 187 | + request_body=request_body, |
| 188 | + header={"X-Security-Token": session_token}, |
| 189 | + action="GetRawApiKey", |
| 190 | + ak=access_key, |
| 191 | + sk=secret_key, |
| 192 | + service="ark", |
| 193 | + version="2024-01-01", |
| 194 | + region=region, |
| 195 | + host=host, |
| 196 | + ) |
| 197 | + except requests.exceptions.RequestException as error: |
| 198 | + if attempt >= _RAW_API_KEY_MAX_ATTEMPTS: |
| 199 | + raise ValueError("Failed to get ARK api key.") from error |
| 200 | + logger.warning( |
| 201 | + "GetRawApiKey request failed; retrying " |
| 202 | + f"({attempt}/{_RAW_API_KEY_MAX_ATTEMPTS}): {error}" |
| 203 | + ) |
| 204 | + _sleep_before_raw_api_key_retry(attempt) |
| 205 | + continue |
| 206 | + |
| 207 | + try: |
| 208 | + api_key = res["Result"]["ApiKey"] |
| 209 | + logger.info("Successfully fetched ARK API Key.") |
| 210 | + return api_key |
| 211 | + except KeyError as error: |
| 212 | + if ( |
| 213 | + attempt < _RAW_API_KEY_MAX_ATTEMPTS |
| 214 | + and _is_retryable_raw_api_key_response(res) |
| 215 | + ): |
| 216 | + logger.warning( |
| 217 | + "GetRawApiKey returned a retryable error; retrying " |
| 218 | + f"({attempt}/{_RAW_API_KEY_MAX_ATTEMPTS}): " |
| 219 | + f"{_response_error(res)}" |
| 220 | + ) |
| 221 | + _sleep_before_raw_api_key_retry(attempt) |
| 222 | + continue |
| 223 | + raise ValueError(f"Failed to get ARK api key: {res}") from error |
| 224 | + |
| 225 | + raise ValueError("Failed to get ARK api key.") |
0 commit comments