Skip to content

Commit 5db47dc

Browse files
committed
retry tao price shovel request on corrupted CMC data
1 parent 472232c commit 5db47dc

File tree

1 file changed

+50
-16
lines changed

1 file changed

+50
-16
lines changed

scraper_service/shovel_tao_price/cmc_client.py

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ def fetch_cmc_data(params, endpoint):
2222
try:
2323
response = requests.get(url, headers=headers, params=params, timeout=30) # Add timeout
2424
except requests.Timeout:
25+
logging.warning("CMC API request timed out")
2526
raise ShovelProcessingError("CMC API request timed out")
2627
except requests.ConnectionError:
28+
logging.warning("Failed to connect to CMC API")
2729
raise ShovelProcessingError("Failed to connect to CMC API")
2830

2931
# Handle rate limiting explicitly
3032
if response.status_code == 429:
33+
retry_after = int(response.headers.get('Retry-After', 60))
34+
logging.warning(f"CMC API rate limit exceeded, retry after {retry_after} seconds")
3135
raise ShovelProcessingError("CMC API rate limit exceeded")
3236

3337
# Handle other common error codes
@@ -36,25 +40,55 @@ def fetch_cmc_data(params, endpoint):
3640
elif response.status_code == 403:
3741
raise ShovelProcessingError("CMC API access forbidden")
3842
elif response.status_code >= 500:
43+
logging.warning(f"CMC API server error: {response.status_code}")
3944
raise ShovelProcessingError(f"CMC API server error: {response.status_code}")
4045
elif response.status_code != 200:
46+
logging.warning(f"CMC API request failed with status code: {response.status_code}")
4147
raise ShovelProcessingError(f"CMC API request failed with status code: {response.status_code}")
4248

4349
try:
4450
data = response.json()
4551
except ValueError:
52+
logging.warning("Failed to parse CMC API response as JSON")
4653
raise ShovelProcessingError("Failed to parse CMC API response as JSON")
4754

4855
# Check for API-level errors
4956
if 'status' in data and 'error_code' in data['status'] and data['status']['error_code'] != 0:
5057
error_message = data['status'].get('error_message', 'Unknown API error')
58+
logging.warning(f"CMC API error: {error_message}")
5159
raise ShovelProcessingError(f"CMC API error: {error_message}")
5260

61+
if 'data' not in data:
62+
logging.warning("Invalid CMC API response: missing 'data' field")
63+
raise DatabaseConnectionError("Invalid CMC API response: missing 'data' field")
64+
if 'quotes' not in data['data']:
65+
logging.warning("Invalid CMC API response: missing 'quotes' field")
66+
raise DatabaseConnectionError("Invalid CMC API response: missing 'quotes' field")
67+
if not data['data']['quotes']:
68+
logging.warning(f"No price data available for timestamp {params.get('time_start', 'latest')}")
69+
raise DatabaseConnectionError(f"No price data available for timestamp {params.get('time_start', 'latest')}")
70+
71+
quote = data['data']['quotes'][0] if endpoint == 'historical' else data['data'][str(CMC_TAO_ID)]
72+
if 'quote' not in quote or 'USD' not in quote['quote']:
73+
logging.warning("Invalid CMC API response: missing USD quote data")
74+
raise DatabaseConnectionError("Invalid CMC API response: missing USD quote data")
75+
76+
usd_quote = quote['quote']['USD']
77+
required_fields = ['price', 'market_cap', 'volume_24h']
78+
for field in required_fields:
79+
if field not in usd_quote:
80+
logging.warning(f"Invalid CMC API response: missing {field} field")
81+
raise DatabaseConnectionError(f"Invalid CMC API response: missing {field} field")
82+
if usd_quote[field] is None:
83+
logging.warning(f"Invalid CMC API response: {field} is None")
84+
raise DatabaseConnectionError(f"Invalid CMC API response: {field} is None")
85+
5386
return data, response.status_code
54-
except requests.exceptions.RequestException as e:
55-
raise ShovelProcessingError(f"Failed to make CMC API request: {str(e)}")
87+
except ShovelProcessingError:
88+
raise
5689
except Exception as e:
57-
raise ShovelProcessingError(f"Unexpected error in CMC API request: {str(e)}")
90+
logging.warning(f"Unexpected error in CMC API request: {str(e)}")
91+
raise DatabaseConnectionError(f"Unexpected error in CMC API request: {str(e)}")
5892

5993
def get_price_by_time(timestamp):
6094
if timestamp is None or timestamp <= 0:
@@ -93,23 +127,23 @@ def get_price_by_time(timestamp):
93127
logging.debug(f"Got response with status code: {status_code}")
94128

95129
if 'data' not in data:
96-
raise ShovelProcessingError(f"Invalid CMC API response: missing 'data' field")
130+
raise DatabaseConnectionError(f"Invalid CMC API response: missing 'data' field")
97131
if 'quotes' not in data['data']:
98-
raise ShovelProcessingError(f"Invalid CMC API response: missing 'quotes' field")
132+
raise DatabaseConnectionError(f"Invalid CMC API response: missing 'quotes' field")
99133
if not data['data']['quotes']:
100-
raise ShovelProcessingError(f"No price data available for timestamp {timestamp}")
134+
raise DatabaseConnectionError(f"No price data available for timestamp {timestamp}")
101135

102136
quote = data['data']['quotes'][0]
103137
if 'quote' not in quote or 'USD' not in quote['quote']:
104-
raise ShovelProcessingError(f"Invalid CMC API response: missing USD quote data")
138+
raise DatabaseConnectionError(f"Invalid CMC API response: missing USD quote data")
105139

106140
usd_quote = quote['quote']['USD']
107141
required_fields = ['price', 'market_cap', 'volume_24h']
108142
for field in required_fields:
109143
if field not in usd_quote:
110-
raise ShovelProcessingError(f"Invalid CMC API response: missing {field} field")
144+
raise DatabaseConnectionError(f"Invalid CMC API response: missing {field} field")
111145
if usd_quote[field] is None:
112-
raise ShovelProcessingError(f"Invalid CMC API response: {field} is None")
146+
raise DatabaseConnectionError(f"Invalid CMC API response: {field} is None")
113147

114148
price = usd_quote['price']
115149
market_cap = usd_quote['market_cap']
@@ -125,7 +159,7 @@ def get_price_by_time(timestamp):
125159
except ShovelProcessingError:
126160
raise
127161
except Exception as e:
128-
raise ShovelProcessingError(f"Failed to get price data: {str(e)}")
162+
raise DatabaseConnectionError(f"Failed to get price data: {str(e)}")
129163

130164
def get_latest_price():
131165
try:
@@ -137,23 +171,23 @@ def get_latest_price():
137171
data, status_code = fetch_cmc_data(parameters, 'latest')
138172

139173
if 'data' not in data:
140-
raise ShovelProcessingError(f"Invalid CMC API response: missing 'data' field")
174+
raise DatabaseConnectionError(f"Invalid CMC API response: missing 'data' field")
141175

142176
tao_id_str = str(CMC_TAO_ID)
143177
if tao_id_str not in data['data']:
144-
raise ShovelProcessingError(f"No data available for TAO (ID: {CMC_TAO_ID})")
178+
raise DatabaseConnectionError(f"No data available for TAO (ID: {CMC_TAO_ID})")
145179

146180
tao_data = data['data'][tao_id_str]
147181
if 'quote' not in tao_data or 'USD' not in tao_data['quote']:
148-
raise ShovelProcessingError(f"Invalid CMC API response: missing USD quote data")
182+
raise DatabaseConnectionError(f"Invalid CMC API response: missing USD quote data")
149183

150184
usd_quote = tao_data['quote']['USD']
151185
required_fields = ['price', 'market_cap', 'volume_24h']
152186
for field in required_fields:
153187
if field not in usd_quote:
154-
raise ShovelProcessingError(f"Invalid CMC API response: missing {field} field")
188+
raise DatabaseConnectionError(f"Invalid CMC API response: missing {field} field")
155189
if usd_quote[field] is None:
156-
raise ShovelProcessingError(f"Invalid CMC API response: {field} is None")
190+
raise DatabaseConnectionError(f"Invalid CMC API response: {field} is None")
157191

158192
price = usd_quote['price']
159193
market_cap = usd_quote['market_cap']
@@ -168,4 +202,4 @@ def get_latest_price():
168202
except ShovelProcessingError:
169203
raise
170204
except Exception as e:
171-
raise ShovelProcessingError(f"Failed to get latest price data: {str(e)}")
205+
raise DatabaseConnectionError(f"Failed to get latest price data: {str(e)}")

0 commit comments

Comments
 (0)