Spaces:
Running
Running
File size: 3,401 Bytes
91e3cb8 3247df2 91e3cb8 3247df2 dc055c2 3247df2 dc055c2 57abcef 91e3cb8 3247df2 b1e2dca 3247df2 b1e2dca 3247df2 b1e2dca 3247df2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | from fastapi import FastAPI
import os, time, requests
app = FastAPI()
# === CONFIG ===
BASE = os.getenv("DB3_BASE_URL", "https://alesamodio-db3-update.hf.space") # receiver base URL
CRON_SECRET = os.getenv("CRON_SECRET", "") # receiver's /run secret (set in receiver Space)
HF_TOKEN = os.getenv("HF_TOKEN", "") # READ token if receiver is PRIVATE (set in this trigger Space)
# Timings (tune if needed; can also override via query params)
DEFAULT_WARMUP_WAIT_S = int(os.getenv("WARMUP_WAIT_S", "180")) # quiet wait after first wake
READY_INTERVAL_S = int(os.getenv("READY_INTERVAL_S", "20")) # poll cadence
READY_MAX_ATTEMPTS = int(os.getenv("READY_MAX_ATTEMPTS", "15")) # ~5 min total
def _headers():
return {"Authorization": f"Bearer {HF_TOKEN}"} if HF_TOKEN else {}
@app.get("/")
def home():
return {"status": "running", "message": "HF trigger alive"}
@app.get("/run")
def run():
"""
Wake receiver once -> quiet wait -> poll /ready -> fire /run?secret=...
Optional query overrides:
warmup_wait (int seconds), max_attempts, interval
"""
log = []
warmup_wait = int(os.getenv("WARMUP_WAIT_S", str(DEFAULT_WARMUP_WAIT_S)))
# allow query overrides without importing FastAPI Request
try:
import starlette.requests
# no-op; just to avoid extra dependency notes
except Exception:
pass
# simple query parsing without typing Request
from fastapi import Request
def get_query():
# tiny helper because we didn't annotate Request in signature
import inspect
frame = inspect.currentframe().f_back
req = frame.f_locals.get('request') # not available in this simple handler
return {}
# actual overrides via os env only to keep it minimal
max_attempts = READY_MAX_ATTEMPTS
interval = READY_INTERVAL_S
# --- 1) Wake once (GET /) ---
try:
r = requests.get(f"{BASE}/", headers=_headers(), timeout=10)
log.append(f"wake: {r.status_code}")
except Exception as e:
log.append(f"wake_err: {e}")
# --- 2) Quiet wait to let models load ---
time.sleep(warmup_wait)
log.append(f"quiet_wait_done: {warmup_wait}s")
# --- 3) Poll /ready ---
ready = False
last_text = ""
for i in range(1, max_attempts + 1):
try:
rr = requests.get(f"{BASE}/ready", headers=_headers(), timeout=10)
last_text = rr.text
if rr.ok and '"ready"' in rr.text:
log.append(f"ready_yes_at_attempt:{i}")
ready = True
break
else:
log.append(f"ready_no_{i}: {rr.status_code} {rr.text[:80]}")
except Exception as e:
log.append(f"ready_err_{i}: {e}")
time.sleep(interval)
if not ready:
return {
"status": "not_ready",
"last_ready_response": last_text[:200],
"log": log
}
# --- 4) Fire /run with secret ---
try:
run_url = f"{BASE}/run?secret={CRON_SECRET}"
final = requests.get(run_url, headers=_headers(), timeout=600)
return {
"status": "ok",
"code": final.status_code,
"body": (final.text[:2000] if final.text else ""),
"log": log
}
except Exception as e:
return {"status": "run_error", "error": str(e), "log": log}
|