fester/backend/recommend.py

116 lines
2.6 KiB
Python

from governor import thermal_cap
from cache import make_build_key, cache_hit
# ----------------------------
# analyze cluster health
# ----------------------------
def cluster_heat(nodes):
if not nodes:
return 0.5
total = 0
count = 0
for n in nodes:
agent = n.get("agent") or {}
load = agent.get("load", "1 1 1")
try:
total += float(load.split()[0])
except:
total += 1.0
count += 1
return total / max(count, 1)
# ----------------------------
# thermal risk scoring
# ----------------------------
def risk_level(node):
agent = node.get("agent") or {}
cap = thermal_cap(agent)
if cap < 0.3:
return "HIGH_RISK"
elif cap < 0.6:
return "MODERATE"
return "SAFE"
# ----------------------------
# predict build cost
# ----------------------------
def estimate_build_cost(nodes):
cost = 0.0
for n in nodes:
agent = n.get("agent") or {}
load = agent.get("load", "1 1 1")
try:
cost += float(load.split()[0])
except:
cost += 1.0
return cost / max(len(nodes), 1)
# ----------------------------
# recommendation engine
# ----------------------------
def recommend(project, snapshot, nodes):
recommendations = {
"build_now": True,
"risk": "SAFE",
"cache_likely": False,
"preferred_nodes": [],
"reason": []
}
# ----------------------------
# cache prediction
# ----------------------------
key_sample = make_build_key(
snapshot["hash"],
list(project["targets"].keys())[0],
project.get("build_env", {})
)
if cache_hit(key_sample):
recommendations["cache_likely"] = True
recommendations["reason"].append("Cache hit likely for current snapshot")
# ----------------------------
# cluster load analysis
# ----------------------------
heat = cluster_heat(nodes)
if heat > 3.0:
recommendations["build_now"] = False
recommendations["reason"].append("Cluster overloaded - recommend delay")
# ----------------------------
# node filtering
# ----------------------------
safe_nodes = []
for n in nodes:
if risk_level(n) == "SAFE":
safe_nodes.append(n["name"])
recommendations["preferred_nodes"] = safe_nodes
# ----------------------------
# final risk classification
# ----------------------------
if heat > 4.0:
recommendations["risk"] = "HIGH_RISK"
elif heat > 2.5:
recommendations["risk"] = "MODERATE"
return recommendations