QMetaRam / backend /qkernel /healing.py
metarm's picture
Upload folder using huggingface_hub (part 4)
945aae0 verified
Raw History Blame Contribute Delete
3.21 kB
import logging
from typing import Any
logger = logging.getLogger("qkernel.healing")
HEALING_ACTIONS = {
"network_latency": "restart_node",
"memory_leak": "clear_cache",
"null_pointer": "rollback_deploy",
"unknown": "isolate_node",
}
class SelfHealingEngine:
def __init__(self):
self._history: list[dict] = []
def detect(self, metrics: dict) -> bool:
if metrics.get("latency", 0) > 1000:
return True
if metrics.get("error_rate", 0) > 0.2:
return True
return False
def analyze(self, error: str, context: dict | None = None) -> str:
error_lower = error.lower()
if "timeout" in error_lower or "latency" in error_lower:
return "network_latency"
if "memory" in error_lower:
return "memory_leak"
if "null" in error_lower or "none" in error_lower:
return "null_pointer"
return "unknown"
def plan(self, root_cause: str) -> str:
return HEALING_ACTIONS.get(root_cause, "isolate_node")
async def execute(self, action: str, node: Any) -> dict:
result = {"action": action, "success": True, "details": ""}
if action == "restart_node":
if hasattr(node, "restart"):
await node.restart()
result["details"] = "Node restarted"
else:
result["details"] = "Node has no restart method"
elif action == "clear_cache":
if hasattr(node, "cache"):
node.cache.clear()
result["details"] = "Cache cleared"
else:
result["details"] = "Node has no cache attribute"
elif action == "rollback_deploy":
if hasattr(node, "rollback"):
await node.rollback()
result["details"] = "Deployment rolled back"
else:
result["details"] = "Node has no rollback method"
elif action == "isolate_node":
if hasattr(node, "isolated"):
node.isolated = True
result["details"] = "Node isolated from traffic"
else:
result["details"] = "Node has no isolated attribute"
return result
async def handle_failure(self, node: Any, metrics: dict, error: str) -> dict:
if not self.detect(metrics):
return {"status": "healthy"}
root_cause = self.analyze(error)
action = self.plan(root_cause)
exec_result = await self.execute(action, node)
record = {
"error": error,
"root_cause": root_cause,
"action": action,
"result": exec_result,
}
self._history.append(record)
if len(self._history) > 100:
self._history = self._history[-100:]
logger.info(
"Healing: cause=%s action=%s success=%s",
root_cause, action, exec_result["success"],
)
return {
"status": "healed" if exec_result["success"] else "failed",
"root_cause": root_cause,
"action": action,
}
def get_history(self) -> list[dict]:
return list(self._history)