Execution Graph#
Directed acyclic graph (DAG) that composes pipeline modules, resolves dependencies, and drives execution in the correct order.
Builds an execution DAG from a list of modules.
The builder inspects each module’s declared inputs and outputs,
then wires nodes together so that every node’s dependencies point to the
nodes that produce its required inputs.
- class adapt.execution.graph.builder.GraphBuilder(modules)#
Bases:
objectConstruct a directed acyclic graph from module declarations.
- Parameters:
modules (
list[BaseModule]) – Ordered or unordered list of modules to connect. Execution order is determined by input/output matching, not list order.- Raises:
ValueError – If two modules declare the same output key (ambiguous dependency).
Example:: – builder = GraphBuilder([acquisition_mod, ingest_mod, detection_mod, projection_mod]) nodes = builder.build()
Executes a DAG of nodes in dependency order.
The executor runs a simple topological loop: nodes whose dependencies have all completed are eligible to run. This single-threaded executor is the reference implementation. Future steps may add parallel execution.
Contract enforcement#
If a module declares input_contracts or output_contracts, the
executor calls each validator automatically before and after run().
Validators raise ContractViolation on failure; the exception propagates
up to the caller (e.g. RadarProcessor) which handles it.
- class adapt.execution.graph.executor.GraphExecutor(nodes, observability=None)#
Bases:
objectExecute a list of nodes in topological order.
- Parameters:
nodes (
list[Node]) – Connected nodes returned byGraphBuilder.build().Example:: – nodes = GraphBuilder([a, b, c]).build() executor = GraphExecutor(nodes) result_context = executor.run(initial_context={})
observability (Observability | None)
- run(context)#
Execute all nodes in dependency order.
- Parameters:
context (
dict) – Initial data available to the first nodes (e.g. file paths, config). Each node’s outputs are merged into this dict after the node runs, making them available to downstream nodes.- Returns:
Final context containing all module outputs.
- Return type:
dict- Raises:
RuntimeError – If the graph contains a cycle (nodes that can never be ready).
Execution graph node.
Each node wraps a module and tracks its position in the DAG: which nodes it depends on (must complete before this node runs) and which nodes depend on it (notified when this node completes).
- class adapt.execution.graph.node.Node(module)#
Bases:
objectA node in the execution graph.
- Parameters:
module (
BaseModule) – The processing module this node wraps.
- module#
- Type:
BaseModule
- inputs#
Data keys required by this module.
- Type:
list[str]
- outputs#
Data keys produced by this module.
- Type:
list[str]
- property name: str#
Module registry — discover and instantiate registered modules.
Modules register their class at import time by calling registry.register().
The controller calls registry.create_modules() to get instantiated modules
ready for graph construction.
Usage:
# In a module file (modules/detection/module.py):
from adapt.execution.module_registry import registry
class DetectModule(BaseModule):
name = "detection"
inputs = ["grid_volume"]
outputs = ["storm_cells"]
...
registry.register(DetectModule)
# In the controller:
modules = registry.create_modules()
nodes = GraphBuilder(modules).build()
GraphExecutor(nodes).run(context)
- class adapt.execution.module_registry.ModuleRegistry#
Bases:
objectCentral registry for Adapt modules and extensions.
Stores module classes. Instantiates them on demand via
create_modules(). This allows each module to be configured with constructor arguments at runtime while keeping registration declarative.- Raises:
RuntimeError – If the same module name is registered twice.
KeyError – If
get()is called with an unregistered name.
- clear()#
Remove all registered modules (primarily for testing).
- Return type:
None
- create_modules()#
Instantiate and return all registered modules.
- Returns:
One instance per registered module class, in registration order.
- Return type:
list[BaseModule]
- get(name)#
Return the module class registered under
name.- Raises:
KeyError – If no module with that name is registered.
- Return type:
type[BaseModule]- Parameters:
name (str)
- list_modules()#
Return names of all registered modules.
- Return type:
list[str]
- register(module_class)#
Register a module class by its
nameattribute.- Parameters:
module_class (
type[BaseModule]) – The module class to register. Must have a non-emptyname.- Raises:
RuntimeError – If a module with the same name is already registered.
ValueError – If
module_class.nameis empty.
- Return type:
None
- unregister(name)#
Remove a module from the registry (primarily for testing).
- Return type:
None- Parameters:
name (str)