crabbly commited on
Commit
0b29256
·
1 Parent(s): 62d0284

Fix build error

Browse files
Files changed (1) hide show
  1. main.py +30 -9
main.py CHANGED
@@ -22,14 +22,15 @@ HF_TOKEN = os.getenv("HF_TOKEN")
22
  DEV_URL = "https://PPAL-SongLab-UGA-fruit-analyzer-dev.hf.space"
23
  PROD_URL = "https://PPAL-SongLab-UGA-fruit-analyzer.hf.space"
24
  HF_RATE_LIMIT_STATUS = 429
 
25
 
26
 
27
- def request_with_429_backoff(method, url, *, max_retries=3, **kwargs):
28
  last_response = None
29
  for attempt in range(max_retries + 1):
30
  response = method(url, **kwargs)
31
  last_response = response
32
- if response.status_code != HF_RATE_LIMIT_STATUS:
33
  return response
34
 
35
  retry_after = response.headers.get("retry-after")
@@ -38,7 +39,7 @@ def request_with_429_backoff(method, url, *, max_retries=3, **kwargs):
38
  except ValueError:
39
  wait_s = None
40
  if wait_s is None:
41
- wait_s = [2.0, 5.0, 10.0, 15.0][min(attempt, 3)]
42
  if attempt < max_retries:
43
  time.sleep(min(max(wait_s, 0.5), 20.0))
44
  return last_response
@@ -50,8 +51,28 @@ def hf_error_message(exc):
50
  retry_after = response.headers.get("retry-after")
51
  suffix = f" Retry after about {retry_after} seconds." if retry_after else " Please wait a minute and try again."
52
  return f"Hugging Face is rate limiting this Space after several retry attempts.{suffix}"
 
 
 
 
 
 
53
  return str(exc)
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  @app.get("/")
56
  def read_root():
57
  return {"status": "Render Proxy is awake!"}
@@ -97,7 +118,7 @@ async def proxy_process(request: Request, file: UploadFile = File(...), password
97
 
98
  # FIX: Define the blocking request
99
  def make_post():
100
- return request_with_429_backoff(
101
  requests.post,
102
  target_url,
103
  headers=headers,
@@ -112,7 +133,7 @@ async def proxy_process(request: Request, file: UploadFile = File(...), password
112
  response.raise_for_status()
113
  return response.json()
114
  except requests.exceptions.RequestException as e:
115
- return {"success": False, "message": f"Proxy Error (Hugging Face): {hf_error_message(e)}"}
116
  except Exception as e:
117
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}"}
118
 
@@ -135,7 +156,7 @@ async def proxy_compatibility(request: Request, password: str = Form(""), userna
135
  data.setdefault("username", username)
136
 
137
  def make_post():
138
- return request_with_429_backoff(
139
  requests.post,
140
  target_url,
141
  headers=headers,
@@ -149,7 +170,7 @@ async def proxy_compatibility(request: Request, password: str = Form(""), userna
149
  response.raise_for_status()
150
  return response.json()
151
  except requests.exceptions.RequestException as e:
152
- return {"success": False, "message": f"Proxy Error (Hugging Face): {hf_error_message(e)}", "results": []}
153
  except Exception as e:
154
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "results": []}
155
 
@@ -162,7 +183,7 @@ async def proxy_batch_stage(payload: dict = Body(...)):
162
  headers = {"Authorization": f"Bearer {HF_TOKEN}"}
163
 
164
  def make_post():
165
- return request_with_429_backoff(
166
  requests.post,
167
  target_url,
168
  headers=headers,
@@ -175,7 +196,7 @@ async def proxy_batch_stage(payload: dict = Body(...)):
175
  response.raise_for_status()
176
  return response.json()
177
  except requests.exceptions.RequestException as e:
178
- return {"success": False, "message": f"Proxy Error (Hugging Face): {hf_error_message(e)}", "rows": []}
179
  except Exception as e:
180
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "rows": []}
181
 
 
22
  DEV_URL = "https://PPAL-SongLab-UGA-fruit-analyzer-dev.hf.space"
23
  PROD_URL = "https://PPAL-SongLab-UGA-fruit-analyzer.hf.space"
24
  HF_RATE_LIMIT_STATUS = 429
25
+ HF_TRANSIENT_STATUS = {429, 502, 503, 504}
26
 
27
 
28
+ def request_with_hf_backoff(method, url, *, max_retries=3, **kwargs):
29
  last_response = None
30
  for attempt in range(max_retries + 1):
31
  response = method(url, **kwargs)
32
  last_response = response
33
+ if response.status_code not in HF_TRANSIENT_STATUS:
34
  return response
35
 
36
  retry_after = response.headers.get("retry-after")
 
39
  except ValueError:
40
  wait_s = None
41
  if wait_s is None:
42
+ wait_s = [2.0, 5.0, 10.0, 15.0][min(attempt, 3)] if response.status_code == HF_RATE_LIMIT_STATUS else [3.0, 8.0, 15.0, 20.0][min(attempt, 3)]
43
  if attempt < max_retries:
44
  time.sleep(min(max(wait_s, 0.5), 20.0))
45
  return last_response
 
51
  retry_after = response.headers.get("retry-after")
52
  suffix = f" Retry after about {retry_after} seconds." if retry_after else " Please wait a minute and try again."
53
  return f"Hugging Face is rate limiting this Space after several retry attempts.{suffix}"
54
+ if response is not None and response.status_code in {502, 503, 504}:
55
+ return "Hugging Face Space is temporarily unavailable or waking up after several retry attempts. Please wait a moment and try again."
56
+ if isinstance(exc, requests.exceptions.Timeout):
57
+ return "Hugging Face Space did not respond before the proxy timeout. Please try again."
58
+ if isinstance(exc, requests.exceptions.ConnectionError):
59
+ return "Could not connect to the Hugging Face Space. Please try again."
60
  return str(exc)
61
 
62
+
63
+ def is_retryable_hf_exception(exc):
64
+ response = getattr(exc, "response", None)
65
+ return bool(response is not None and response.status_code in HF_TRANSIENT_STATUS)
66
+
67
+
68
+ def proxy_error_payload(prefix, exc, **extra):
69
+ return {
70
+ "success": False,
71
+ "message": f"{prefix}: {hf_error_message(exc)}",
72
+ "retryable": is_retryable_hf_exception(exc),
73
+ **extra,
74
+ }
75
+
76
  @app.get("/")
77
  def read_root():
78
  return {"status": "Render Proxy is awake!"}
 
118
 
119
  # FIX: Define the blocking request
120
  def make_post():
121
+ return request_with_hf_backoff(
122
  requests.post,
123
  target_url,
124
  headers=headers,
 
133
  response.raise_for_status()
134
  return response.json()
135
  except requests.exceptions.RequestException as e:
136
+ return proxy_error_payload("Proxy Error (Hugging Face)", e)
137
  except Exception as e:
138
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}"}
139
 
 
156
  data.setdefault("username", username)
157
 
158
  def make_post():
159
+ return request_with_hf_backoff(
160
  requests.post,
161
  target_url,
162
  headers=headers,
 
170
  response.raise_for_status()
171
  return response.json()
172
  except requests.exceptions.RequestException as e:
173
+ return proxy_error_payload("Proxy Error (Hugging Face)", e, results=[])
174
  except Exception as e:
175
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "results": []}
176
 
 
183
  headers = {"Authorization": f"Bearer {HF_TOKEN}"}
184
 
185
  def make_post():
186
+ return request_with_hf_backoff(
187
  requests.post,
188
  target_url,
189
  headers=headers,
 
196
  response.raise_for_status()
197
  return response.json()
198
  except requests.exceptions.RequestException as e:
199
+ return proxy_error_payload("Proxy Error (Hugging Face)", e, rows=[])
200
  except Exception as e:
201
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "rows": []}
202