fester/backend/graph/critical_path.py

65 lines
1.6 KiB
Python

# graph/critical_path.py
def compute_critical_path(actions):
"""
Computes the longest dependency-weighted path in a build DAG.
This represents the true bottleneck chain ("critical path")
that determines total build time.
"""
# -----------------------------
# Build adjacency + cost map
# -----------------------------
graph = {}
duration = {}
for action in actions:
name = action["name"]
deps = action.get("deps", [])
graph[name] = deps
# fallback cost model (later replace with real timing data)
duration[name] = action.get("cost", 1)
# -----------------------------
# memoized DFS for longest path
# -----------------------------
memo = {}
def dfs(node):
if node in memo:
return memo[node]
# leaf node
if node not in graph or not graph[node]:
memo[node] = duration.get(node, 1)
return memo[node]
best_dep = 0
for dep in graph[node]:
best_dep = max(best_dep, dfs(dep))
memo[node] = best_dep + duration.get(node, 1)
return memo[node]
# -----------------------------
# find worst (critical) endpoint
# -----------------------------
critical_node = None
critical_score = -1
for node in graph.keys():
score = dfs(node)
if score > critical_score:
critical_score = score
critical_node = node
return {
"critical_node": critical_node,
"critical_score": critical_score,
"score_map": memo
}