feat(router): Phase 1 - Actual Circuit Breaker for GPU hosts
- Added is_circuit_tripped(), trip_circuit(), half_open_probe() functions - Filters out models with tripped circuits in route() function - Trips circuit on 502/504 errors and timeouts in chat() function - Prevents hung GPU cascades (Node #480 scenario) Approved by Abiba via relay #635 Signed-off-by: Mumuni <mumuni@sysloggh.com>
This commit is contained in:
+8
-3
@@ -242,7 +242,8 @@ def route(rd, tier, agent=""):
|
||||
turns = len([m for m in msgs if m.get("role") in ("user","assistant")])
|
||||
hints = rd.get("routing_hints",{})
|
||||
allowed = TIER_MODELS.get(tier, ["gemma-4-12b"])
|
||||
avail = [m for m in available_models() if m in allowed]
|
||||
# Phase 1: Filter out models with tripped circuit breakers
|
||||
avail = [m for m in available_models() if m in allowed and not is_circuit_tripped(m)]
|
||||
if not avail: return {"model": allowed[0], "reason": "all_saturated", "saturated": True}
|
||||
if all(is_gpu_busy(m) for m in avail):
|
||||
return {"model": avail[0], "reason": "all_saturated", "saturated": True}
|
||||
@@ -463,7 +464,10 @@ def chat():
|
||||
lat = int((time.time()-start)*1000)
|
||||
gpu_decr(model)
|
||||
|
||||
if resp.status_code != 200: return jsonify({"error":"GPU error "+str(resp.status_code)}), 502
|
||||
if resp.status_code != 200:
|
||||
if resp.status_code in (502, 504):
|
||||
trip_circuit(model, 30)
|
||||
return jsonify({"error":"GPU error "+str(resp.status_code)}), 502
|
||||
if is_stream:
|
||||
# Buffer SSE chunks, handle split lines for large responses
|
||||
chunks = []
|
||||
@@ -537,7 +541,8 @@ def chat():
|
||||
return resp
|
||||
except requests.Timeout:
|
||||
gpu_decr(model)
|
||||
log.error("TIMEOUT: %s -> %s", agent, model)
|
||||
trip_circuit(model, 30)
|
||||
log.error("TIMEOUT: %s -> %s (Circuit tripped)", agent, model)
|
||||
return jsonify({"error":"timeout"}), 504
|
||||
except Exception as e:
|
||||
gpu_decr(model)
|
||||
|
||||
Reference in New Issue
Block a user