MainTaskComposer
Purpose
The MainTaskComposer builds a Task/LeafTask tree (MainTask) starting
from a command map entry and the current Component Manager context.
It resolves:
the root task properties (execution type and allowed conditions),
nested task composition,
subsystem selection and argument binding based on available resources,
generation of INTERNAL tasks targeting Component Manager methods.
Composition workflow
The composition process is initiated by calling compose():
The command entry is retrieved from the command map using the command name.
The allowed execution conditions are extracted (attribute name and allowed values).
A draft Task tree is created recursively from the map.
During recursive composition, handler-based tasks may either:
create the corresponding LeafTask/Task,
return no task if no suitable target is available, or
raise a
CommandErrorif the task definition requires strict composition throughreject_missing=Trueand a requested target cannot be converted into a valid executable task.
Empty branches are removed (tasks with no subtasks are discarded).
Trackers are instantiated for the remaining Task nodes.
Recursive task building
Task nodes are built according to two patterns:
Composite tasks (contain
typeandtaskskeys) These produce a Task with a list of subtasks. Subtasks may themselves be composite tasks or handler keywords.Handler keywords Keywords such as
cbf,pss,pst,csp_subsandinternalare resolved into LeafTasks (or a Task grouping multiple LeafTasks).
Unsupported keywords result in a composition error.
Strict composition with reject_missing
Some handler-based tasks may define reject_missing=True in the
command map.
When this flag is enabled, the composer does not silently skip requested
targets that are unavailable or not in an allowed state. Instead, it
raises a CommandError and aborts task composition. In this case, the
command received by CSP.LMC is rejected at composition time, and no task tree
is passed to the MainTaskExecutor.
This behaviour is currently relevant for command-map entries such as the
configure flow, where the presence and validity of requested
subsystem targets is mandatory for correct execution.
Subsystem selection and guards
For DEVICE LeafTasks, the composer selects target components from the Component Manager context.
For each candidate component, the composer evaluates the guard
condition defined by allowed_states (attr_name and allowed
values) against the component attribute.
Only components matching the guard condition are selected as execution targets.
If a task definition includes reject_missing=True, composition is
rejected with a CommandError when a subsystem/device explicitly
requested by the current resources configuration cannot be turned into a
LeafTask because it is unavailable or not in an allowed state.
Argument binding
For DEVICE tasks, LeafTask input arguments (argin) are derived from
the Component Manager resources configuration.
If no suitable component is found (or no applicable resources exist), the corresponding LeafTask is not created.
However, if the task definition sets reject_missing=True, the
composer raises a CommandError instead of silently omitting the
requested task.
Cleaning of empty branches
After building the draft tree, the composer removes tasks whose list of subtasks is empty.
This ensures that commands with partially unavailable resources can
still produce a valid executable task tree containing only meaningful
actions, provided that strict composition has not been requested through
reject_missing=True.
See also Command map, MainTaskExecutor, and Task Tracker.