Summary
The in-degree counter pattern is already implemented across DAG.Engine and Task.Process, but it's not documented explicitly. Future contributors may not immediately understand the readiness tracking mechanism.
How It Currently Works
- At run start,
DAG.Engine calls build_dep_counts/1 to compute the initial in-degree (number of unresolved dependencies) for each task.
- Each
Task.Process starts with deps_remaining = in_degree[task_id].
- When the Engine receives
{:task_done, run_id, task_id}, it calls Graph.immediate_dependents/2 and sends :dep_done to each dependent's Task.Process.
Task.Process decrements its deps_remaining counter. When it hits 0, the process transitions :pending → :queued automatically and dispatches to a worker.
This means task readiness is evaluated eagerly after each completion — not in waves. As soon as all deps for a task complete, it starts.
Action Items
- Add a module-level
@moduledoc to DAG.Engine explaining the in-degree counter flow
- Add a module-level
@moduledoc to Task.Process explaining the deps_remaining counter
- Add a sequence diagram to
docs/plans/2026-03-05-levicon-mvp.md showing the full task lifecycle
References
lib/levicon/dag/engine.ex — build_dep_counts/1, handle_info({:task_done})
lib/levicon/task/process.ex — deps_remaining, :dep_done cast handler
Summary
The in-degree counter pattern is already implemented across
DAG.EngineandTask.Process, but it's not documented explicitly. Future contributors may not immediately understand the readiness tracking mechanism.How It Currently Works
DAG.Enginecallsbuild_dep_counts/1to compute the initial in-degree (number of unresolved dependencies) for each task.Task.Processstarts withdeps_remaining = in_degree[task_id].{:task_done, run_id, task_id}, it callsGraph.immediate_dependents/2and sends:dep_doneto each dependent'sTask.Process.Task.Processdecrements itsdeps_remainingcounter. When it hits 0, the process transitions:pending → :queuedautomatically and dispatches to a worker.This means task readiness is evaluated eagerly after each completion — not in waves. As soon as all deps for a task complete, it starts.
Action Items
@moduledoctoDAG.Engineexplaining the in-degree counter flow@moduledoctoTask.Processexplaining thedeps_remainingcounterdocs/plans/2026-03-05-levicon-mvp.mdshowing the full task lifecycleReferences
lib/levicon/dag/engine.ex—build_dep_counts/1,handle_info({:task_done})lib/levicon/task/process.ex—deps_remaining,:dep_donecast handler