Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -24,14 +24,16 @@ PERSIST_TO_FILE = os.getenv("PERSIST_TO_FILE", "0").strip() == "1"
|
|
| 24 |
PERSIST_PATH = os.getenv("PERSIST_PATH", "webhook_messages.jsonl").strip()
|
| 25 |
|
| 26 |
# Relay forwarding
|
| 27 |
-
|
|
|
|
|
|
|
| 28 |
RELAY_TIMEOUT = int(os.getenv("RELAY_TIMEOUT", "30"))
|
| 29 |
|
| 30 |
# Dedupe window (seconds). Default 24h.
|
| 31 |
SEEN_TTL_SECONDS = int(os.getenv("SEEN_TTL_SECONDS", "86400"))
|
| 32 |
MAX_SEEN = int(os.getenv("MAX_SEEN", "5000"))
|
| 33 |
|
| 34 |
-
# Limit concurrent forwards (prevents flood
|
| 35 |
MAX_INFLIGHT = int(os.getenv("MAX_INFLIGHT", "1"))
|
| 36 |
|
| 37 |
# -----------------------------------------------------------------------------
|
|
@@ -114,6 +116,12 @@ def _norm(v: Any) -> str:
|
|
| 114 |
return str(v)
|
| 115 |
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
def compute_fingerprint(payload: Dict[str, Any]) -> str:
|
| 118 |
"""
|
| 119 |
Payload-based fingerprint (MVP).
|
|
@@ -153,11 +161,12 @@ app = FastAPI(title="Inserio Relay", version="1.0.0")
|
|
| 153 |
|
| 154 |
@app.get("/health")
|
| 155 |
def health():
|
|
|
|
| 156 |
return {
|
| 157 |
"ok": True,
|
| 158 |
"service": "inserio-relay",
|
| 159 |
"post": ["/webhook/", "/wakeup/"],
|
| 160 |
-
"forward_to":
|
| 161 |
"max_inflight": MAX_INFLIGHT,
|
| 162 |
"seen_ttl_seconds": SEEN_TTL_SECONDS,
|
| 163 |
"total_count": TOTAL_COUNT,
|
|
@@ -167,12 +176,12 @@ def health():
|
|
| 167 |
|
| 168 |
@app.get("/")
|
| 169 |
def root():
|
| 170 |
-
|
| 171 |
return {
|
| 172 |
"ok": True,
|
| 173 |
"service": "inserio-relay",
|
| 174 |
"post": ["/webhook/", "/wakeup/"],
|
| 175 |
-
"forward_to":
|
| 176 |
"max_inflight": MAX_INFLIGHT,
|
| 177 |
"seen_ttl_seconds": SEEN_TTL_SECONDS,
|
| 178 |
}
|
|
@@ -209,7 +218,7 @@ async def webhook(
|
|
| 209 |
now = _now_ts()
|
| 210 |
_gc_seen(now)
|
| 211 |
|
| 212 |
-
#
|
| 213 |
if not _norm(payload.get("sa_processing_state")):
|
| 214 |
payload["sa_processing_state"] = "new"
|
| 215 |
|
|
@@ -219,7 +228,7 @@ async def webhook(
|
|
| 219 |
fp = compute_fingerprint(payload)
|
| 220 |
payload["sa_fingerprint"] = fp
|
| 221 |
|
| 222 |
-
# Dedupe
|
| 223 |
duplicate = fp in SEEN
|
| 224 |
if not duplicate:
|
| 225 |
SEEN[fp] = now
|
|
@@ -244,11 +253,8 @@ async def webhook(
|
|
| 244 |
_append_message(payload=payload, meta=meta, relay=relay_info)
|
| 245 |
return JSONResponse(status_code=200, content=relay_info)
|
| 246 |
|
| 247 |
-
#
|
| 248 |
-
|
| 249 |
-
forward_body = None
|
| 250 |
-
forward_url = f"{WAKEUP_URL}/wakeup"
|
| 251 |
-
|
| 252 |
if duplicate:
|
| 253 |
relay_info = {
|
| 254 |
"ok": True,
|
|
@@ -256,6 +262,7 @@ async def webhook(
|
|
| 256 |
"fingerprint": fp,
|
| 257 |
"forwarded": False,
|
| 258 |
"reason": "duplicate",
|
|
|
|
| 259 |
}
|
| 260 |
meta = {
|
| 261 |
"client": request.client.host if request.client else None,
|
|
@@ -309,6 +316,7 @@ async def webhook(
|
|
| 309 |
# Gradio dashboard
|
| 310 |
# -----------------------------------------------------------------------------
|
| 311 |
def ui_status() -> str:
|
|
|
|
| 312 |
return _safe_json_dumps(
|
| 313 |
{
|
| 314 |
"total_count": TOTAL_COUNT,
|
|
@@ -316,7 +324,7 @@ def ui_status() -> str:
|
|
| 316 |
"buffer_size": len(MESSAGES),
|
| 317 |
"max_buffer": MAX_MESSAGES,
|
| 318 |
"relay": {
|
| 319 |
-
"forward_url":
|
| 320 |
"timeout": RELAY_TIMEOUT,
|
| 321 |
"max_inflight": MAX_INFLIGHT,
|
| 322 |
"seen_size": len(SEEN),
|
|
@@ -346,7 +354,8 @@ def ui_clear() -> str:
|
|
| 346 |
MESSAGES.clear()
|
| 347 |
TOTAL_COUNT = 0
|
| 348 |
LAST_RECEIVED_TS = None
|
| 349 |
-
|
|
|
|
| 350 |
|
| 351 |
|
| 352 |
with gr.Blocks(title="Inserio Relay Dashboard") as demo:
|
|
|
|
| 24 |
PERSIST_PATH = os.getenv("PERSIST_PATH", "webhook_messages.jsonl").strip()
|
| 25 |
|
| 26 |
# Relay forwarding
|
| 27 |
+
# IMPORTANT:
|
| 28 |
+
# WAKEUP_URL must be HOST ONLY (no /wakeup) e.g. http://163.245.192.149:8080
|
| 29 |
+
WAKEUP_URL = os.getenv("WAKEUP_URL", "http://163.245.192.149:8080").strip()
|
| 30 |
RELAY_TIMEOUT = int(os.getenv("RELAY_TIMEOUT", "30"))
|
| 31 |
|
| 32 |
# Dedupe window (seconds). Default 24h.
|
| 33 |
SEEN_TTL_SECONDS = int(os.getenv("SEEN_TTL_SECONDS", "86400"))
|
| 34 |
MAX_SEEN = int(os.getenv("MAX_SEEN", "5000"))
|
| 35 |
|
| 36 |
+
# Limit concurrent forwards (prevents flood)
|
| 37 |
MAX_INFLIGHT = int(os.getenv("MAX_INFLIGHT", "1"))
|
| 38 |
|
| 39 |
# -----------------------------------------------------------------------------
|
|
|
|
| 116 |
return str(v)
|
| 117 |
|
| 118 |
|
| 119 |
+
def _join_url(base: str, path: str) -> str:
|
| 120 |
+
base = (base or "").strip().rstrip("/")
|
| 121 |
+
path = "/" + (path or "").lstrip("/")
|
| 122 |
+
return base + path
|
| 123 |
+
|
| 124 |
+
|
| 125 |
def compute_fingerprint(payload: Dict[str, Any]) -> str:
|
| 126 |
"""
|
| 127 |
Payload-based fingerprint (MVP).
|
|
|
|
| 161 |
|
| 162 |
@app.get("/health")
|
| 163 |
def health():
|
| 164 |
+
forward_url = _join_url(WAKEUP_URL, "/wakeup")
|
| 165 |
return {
|
| 166 |
"ok": True,
|
| 167 |
"service": "inserio-relay",
|
| 168 |
"post": ["/webhook/", "/wakeup/"],
|
| 169 |
+
"forward_to": forward_url,
|
| 170 |
"max_inflight": MAX_INFLIGHT,
|
| 171 |
"seen_ttl_seconds": SEEN_TTL_SECONDS,
|
| 172 |
"total_count": TOTAL_COUNT,
|
|
|
|
| 176 |
|
| 177 |
@app.get("/")
|
| 178 |
def root():
|
| 179 |
+
forward_url = _join_url(WAKEUP_URL, "/wakeup")
|
| 180 |
return {
|
| 181 |
"ok": True,
|
| 182 |
"service": "inserio-relay",
|
| 183 |
"post": ["/webhook/", "/wakeup/"],
|
| 184 |
+
"forward_to": forward_url,
|
| 185 |
"max_inflight": MAX_INFLIGHT,
|
| 186 |
"seen_ttl_seconds": SEEN_TTL_SECONDS,
|
| 187 |
}
|
|
|
|
| 218 |
now = _now_ts()
|
| 219 |
_gc_seen(now)
|
| 220 |
|
| 221 |
+
# Default processing state
|
| 222 |
if not _norm(payload.get("sa_processing_state")):
|
| 223 |
payload["sa_processing_state"] = "new"
|
| 224 |
|
|
|
|
| 228 |
fp = compute_fingerprint(payload)
|
| 229 |
payload["sa_fingerprint"] = fp
|
| 230 |
|
| 231 |
+
# Dedupe
|
| 232 |
duplicate = fp in SEEN
|
| 233 |
if not duplicate:
|
| 234 |
SEEN[fp] = now
|
|
|
|
| 253 |
_append_message(payload=payload, meta=meta, relay=relay_info)
|
| 254 |
return JSONResponse(status_code=200, content=relay_info)
|
| 255 |
|
| 256 |
+
# Do not forward duplicates
|
| 257 |
+
forward_url = _join_url(WAKEUP_URL, "/wakeup")
|
|
|
|
|
|
|
|
|
|
| 258 |
if duplicate:
|
| 259 |
relay_info = {
|
| 260 |
"ok": True,
|
|
|
|
| 262 |
"fingerprint": fp,
|
| 263 |
"forwarded": False,
|
| 264 |
"reason": "duplicate",
|
| 265 |
+
"forward_url": forward_url,
|
| 266 |
}
|
| 267 |
meta = {
|
| 268 |
"client": request.client.host if request.client else None,
|
|
|
|
| 316 |
# Gradio dashboard
|
| 317 |
# -----------------------------------------------------------------------------
|
| 318 |
def ui_status() -> str:
|
| 319 |
+
forward_url = _join_url(WAKEUP_URL, "/wakeup")
|
| 320 |
return _safe_json_dumps(
|
| 321 |
{
|
| 322 |
"total_count": TOTAL_COUNT,
|
|
|
|
| 324 |
"buffer_size": len(MESSAGES),
|
| 325 |
"max_buffer": MAX_MESSAGES,
|
| 326 |
"relay": {
|
| 327 |
+
"forward_url": forward_url,
|
| 328 |
"timeout": RELAY_TIMEOUT,
|
| 329 |
"max_inflight": MAX_INFLIGHT,
|
| 330 |
"seen_size": len(SEEN),
|
|
|
|
| 354 |
MESSAGES.clear()
|
| 355 |
TOTAL_COUNT = 0
|
| 356 |
LAST_RECEIVED_TS = None
|
| 357 |
+
SEEN.clear()
|
| 358 |
+
return "Cleared in-memory messages + seen fingerprints."
|
| 359 |
|
| 360 |
|
| 361 |
with gr.Blocks(title="Inserio Relay Dashboard") as demo:
|