aria / core /execution_scheduler.py
varshithreddy1807's picture
feat: release Repository Intelligence Agent v1.0
d231444
Raw History Blame Contribute Delete
2.56 kB
"""Execution scheduler for grouping BuildTasks into sequential stages of parallelizable work (PH2-022)."""
from __future__ import annotations
import logging
from typing import Dict, List
from core.analysis_registry import AnalysisRegistry
from core.incremental_build_planner import BuildTask
logger = logging.getLogger(__name__)
class ExecutionScheduler:
"""Schedules BuildTasks into topological execution stages to maximize parallelism."""
@staticmethod
def schedule(
tasks: List[BuildTask], registry: AnalysisRegistry
) -> List[List[BuildTask]]:
"""Groups tasks into stages using dynamic level assignment based on DAG dependencies.
Within each stage, tasks are sorted alphabetically by their analysis name to ensure
deterministic execution and event ordering.
"""
task_map = {t.analysis: t for t in tasks}
stages_indices: Dict[str, int] = {}
def get_stage_index(name: str) -> int:
if name in stages_indices:
return stages_indices[name]
node = registry.nodes.get(name)
if not node:
stages_indices[name] = 0
return 0
# Filter dependencies to only those that are scheduled in the plan
relevant_deps = [dep for dep in node.dependencies if dep in task_map]
if not relevant_deps:
stages_indices[name] = 0
return 0
# Stage index is 1 + max of dependency stage indices
stages_indices[name] = 1 + max(
get_stage_index(dep) for dep in relevant_deps
)
return stages_indices[name]
# Calculate stage index for each task
for task in tasks:
get_stage_index(task.analysis)
# Group tasks by stage index
grouped: Dict[int, List[BuildTask]] = {}
for task in tasks:
idx = stages_indices[task.analysis]
if idx not in grouped:
grouped[idx] = []
grouped[idx].append(task)
# Construct sorted list of stages
stages: List[List[BuildTask]] = []
for idx in sorted(grouped.keys()):
# Sort tasks within each stage alphabetically by name for determinism
stage_tasks = sorted(grouped[idx], key=lambda t: t.analysis)
stages.append(stage_tasks)
logger.info(
"Scheduled %d build tasks into %d parallel stages.",
len(tasks),
len(stages),
)
return stages