Files
Radiuma_RnD/Dagster/Radiuma_API/radiuma_api/scheduler.py
T
2026-02-08 04:38:10 +03:30

86 lines
2.9 KiB
Python

from typing import Set
from radiuma_api.task import Task, Status
from radiuma_api.execution_context import ExecutionContext
# Write Codes Here:
class Scheduler:
"""
DAG-based execution scheduler.
Decides WHEN a Task can run based on port readiness and orchestrates execution.
"""
def __init__(self):
self._completed: Set[Task] = set()
self._failed: Set[Task] = set()
def run(self, root: Task, context: ExecutionContext):
"""
Entry point: execute a Workflow or Task graph.
"""
self._execute_task(root, context)
def _execute_task(self, task: Task, context: ExecutionContext):
"""
Execute a task respecting DAG dependencies.
If 'task' is a Workflow (has children), delegate to _run_workflow.
Otherwise, run the leaf task when inputs are ready.
"""
# Skip finished tasks
if task.status in (Status.COMPLETED, Status.FAILED, Status.STOPPED):
return
# Workflow (composite)
if hasattr(task, "children"):
self._run_workflow(task, context)
return
# Leaf Task: must have inputs ready
if not task.check_inputs_ready(context):
# Optional: diagnostic log
print(f"[Scheduler] Task '{task.name}' not ready, skipping for now.")
return
try:
task._set_status(Status.RUNNING)
task.run(context)
task._set_status(Status.COMPLETED)
self._completed.add(task)
except Exception as e:
task._set_status(Status.FAILED)
self._failed.add(task)
# Optional: diagnostic log
print(f"[Scheduler] Task '{task.name}' failed: {e}")
# Re-raise to surface error if caller needs to handle
raise
def _run_workflow(self, workflow: Task, context: ExecutionContext):
"""
Execute children respecting dependencies.
Progress until all children are executed or a deadlock is detected.
"""
workflow._set_status(Status.RUNNING)
remaining = set(workflow.children)
while remaining:
progress_made = False
for child in list(remaining):
if child.check_inputs_ready(context):
self._execute_task(child, context)
remaining.remove(child)
progress_made = True
if not progress_made:
# Deadlock: dependencies not resolvable with current data
raise RuntimeError(
f"Workflow '{workflow.name}' deadlock: unresolved dependencies"
)
# Final workflow status based on children results
if any(c.status == Status.FAILED for c in workflow.children):
workflow._set_status(Status.FAILED)
else:
workflow._set_status(Status.COMPLETED)