Update queueing
Browse files
main.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
import requests
|
| 3 |
from fastapi import FastAPI, UploadFile, File, Form, Query, Request, Body
|
| 4 |
from fastapi.responses import Response
|
|
@@ -20,6 +21,36 @@ HF_TOKEN = os.getenv("HF_TOKEN")
|
|
| 20 |
|
| 21 |
DEV_URL = "https://PPAL-SongLab-UGA-fruit-analyzer-dev.hf.space"
|
| 22 |
PROD_URL = "https://PPAL-SongLab-UGA-fruit-analyzer.hf.space"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
@app.get("/")
|
| 25 |
def read_root():
|
|
@@ -66,7 +97,14 @@ async def proxy_process(request: Request, file: UploadFile = File(...), password
|
|
| 66 |
|
| 67 |
# FIX: Define the blocking request
|
| 68 |
def make_post():
|
| 69 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
try:
|
| 72 |
# FIX: Run it in a background thread so other users can check the status!
|
|
@@ -74,7 +112,7 @@ async def proxy_process(request: Request, file: UploadFile = File(...), password
|
|
| 74 |
response.raise_for_status()
|
| 75 |
return response.json()
|
| 76 |
except requests.exceptions.RequestException as e:
|
| 77 |
-
return {"success": False, "message": f"Proxy Error (Hugging Face): {
|
| 78 |
except Exception as e:
|
| 79 |
return {"success": False, "message": f"Proxy Error (Internal): {str(e)}"}
|
| 80 |
|
|
@@ -87,14 +125,20 @@ async def proxy_batch_stage(payload: dict = Body(...)):
|
|
| 87 |
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
|
| 88 |
|
| 89 |
def make_post():
|
| 90 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
try:
|
| 93 |
response = await run_in_threadpool(make_post)
|
| 94 |
response.raise_for_status()
|
| 95 |
return response.json()
|
| 96 |
except requests.exceptions.RequestException as e:
|
| 97 |
-
return {"success": False, "message": f"Proxy Error (Hugging Face): {
|
| 98 |
except Exception as e:
|
| 99 |
return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "rows": []}
|
| 100 |
|
|
|
|
| 1 |
import os
|
| 2 |
+
import time
|
| 3 |
import requests
|
| 4 |
from fastapi import FastAPI, UploadFile, File, Form, Query, Request, Body
|
| 5 |
from fastapi.responses import Response
|
|
|
|
| 21 |
|
| 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")
|
| 36 |
+
try:
|
| 37 |
+
wait_s = float(retry_after) if retry_after else None
|
| 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
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def hf_error_message(exc):
|
| 48 |
+
response = getattr(exc, "response", None)
|
| 49 |
+
if response is not None and response.status_code == HF_RATE_LIMIT_STATUS:
|
| 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():
|
|
|
|
| 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,
|
| 104 |
+
files=files,
|
| 105 |
+
data=data,
|
| 106 |
+
timeout=120,
|
| 107 |
+
)
|
| 108 |
|
| 109 |
try:
|
| 110 |
# FIX: Run it in a background thread so other users can check the status!
|
|
|
|
| 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 |
|
|
|
|
| 125 |
headers = {"Authorization": f"Bearer {HF_TOKEN}"}
|
| 126 |
|
| 127 |
def make_post():
|
| 128 |
+
return request_with_429_backoff(
|
| 129 |
+
requests.post,
|
| 130 |
+
target_url,
|
| 131 |
+
headers=headers,
|
| 132 |
+
json=payload,
|
| 133 |
+
timeout=120,
|
| 134 |
+
)
|
| 135 |
|
| 136 |
try:
|
| 137 |
response = await run_in_threadpool(make_post)
|
| 138 |
response.raise_for_status()
|
| 139 |
return response.json()
|
| 140 |
except requests.exceptions.RequestException as e:
|
| 141 |
+
return {"success": False, "message": f"Proxy Error (Hugging Face): {hf_error_message(e)}", "rows": []}
|
| 142 |
except Exception as e:
|
| 143 |
return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "rows": []}
|
| 144 |
|