@@ -22,12 +22,16 @@ def fetch_cmc_data(params, endpoint):
22
22
try :
23
23
response = requests .get (url , headers = headers , params = params , timeout = 30 ) # Add timeout
24
24
except requests .Timeout :
25
+ logging .warning ("CMC API request timed out" )
25
26
raise ShovelProcessingError ("CMC API request timed out" )
26
27
except requests .ConnectionError :
28
+ logging .warning ("Failed to connect to CMC API" )
27
29
raise ShovelProcessingError ("Failed to connect to CMC API" )
28
30
29
31
# Handle rate limiting explicitly
30
32
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" )
31
35
raise ShovelProcessingError ("CMC API rate limit exceeded" )
32
36
33
37
# Handle other common error codes
@@ -36,25 +40,55 @@ def fetch_cmc_data(params, endpoint):
36
40
elif response .status_code == 403 :
37
41
raise ShovelProcessingError ("CMC API access forbidden" )
38
42
elif response .status_code >= 500 :
43
+ logging .warning (f"CMC API server error: { response .status_code } " )
39
44
raise ShovelProcessingError (f"CMC API server error: { response .status_code } " )
40
45
elif response .status_code != 200 :
46
+ logging .warning (f"CMC API request failed with status code: { response .status_code } " )
41
47
raise ShovelProcessingError (f"CMC API request failed with status code: { response .status_code } " )
42
48
43
49
try :
44
50
data = response .json ()
45
51
except ValueError :
52
+ logging .warning ("Failed to parse CMC API response as JSON" )
46
53
raise ShovelProcessingError ("Failed to parse CMC API response as JSON" )
47
54
48
55
# Check for API-level errors
49
56
if 'status' in data and 'error_code' in data ['status' ] and data ['status' ]['error_code' ] != 0 :
50
57
error_message = data ['status' ].get ('error_message' , 'Unknown API error' )
58
+ logging .warning (f"CMC API error: { error_message } " )
51
59
raise ShovelProcessingError (f"CMC API error: { error_message } " )
52
60
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
+
53
86
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
56
89
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 )} " )
58
92
59
93
def get_price_by_time (timestamp ):
60
94
if timestamp is None or timestamp <= 0 :
@@ -93,23 +127,23 @@ def get_price_by_time(timestamp):
93
127
logging .debug (f"Got response with status code: { status_code } " )
94
128
95
129
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" )
97
131
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" )
99
133
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 } " )
101
135
102
136
quote = data ['data' ]['quotes' ][0 ]
103
137
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" )
105
139
106
140
usd_quote = quote ['quote' ]['USD' ]
107
141
required_fields = ['price' , 'market_cap' , 'volume_24h' ]
108
142
for field in required_fields :
109
143
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" )
111
145
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" )
113
147
114
148
price = usd_quote ['price' ]
115
149
market_cap = usd_quote ['market_cap' ]
@@ -125,7 +159,7 @@ def get_price_by_time(timestamp):
125
159
except ShovelProcessingError :
126
160
raise
127
161
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 )} " )
129
163
130
164
def get_latest_price ():
131
165
try :
@@ -137,23 +171,23 @@ def get_latest_price():
137
171
data , status_code = fetch_cmc_data (parameters , 'latest' )
138
172
139
173
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" )
141
175
142
176
tao_id_str = str (CMC_TAO_ID )
143
177
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 } )" )
145
179
146
180
tao_data = data ['data' ][tao_id_str ]
147
181
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" )
149
183
150
184
usd_quote = tao_data ['quote' ]['USD' ]
151
185
required_fields = ['price' , 'market_cap' , 'volume_24h' ]
152
186
for field in required_fields :
153
187
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" )
155
189
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" )
157
191
158
192
price = usd_quote ['price' ]
159
193
market_cap = usd_quote ['market_cap' ]
@@ -168,4 +202,4 @@ def get_latest_price():
168
202
except ShovelProcessingError :
169
203
raise
170
204
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