116 lines
2.6 KiB
Python
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
|