The component model defines how user algorithm modules plug into PuppetMaster. It builds on the previous runtime context work: components declare their endpoints and triggers, then the runtime drives a small lifecycle around that declaration.
The interface is intentionally narrow:
ComponentSpecdescribes what a module needsComponentimplements the algorithm moduleComponentContextgives the module access to runtime servicesRuntimeContextowns registration and lifecycle state
Transport details stay behind Reader, Writer, and Transport. Scheduler
details stay out of the component interface for now.
ComponentSpec remains the declarative part of a module:
- component name
- description
- reader endpoints
- writer endpoints
- trigger specs
This lets the runtime inspect a component before it starts executing. The scheduler can later use the same spec to wire periodic, data-driven, dependency, or manual triggers.
Component is the runtime-facing base class for algorithm modules:
class MyAlgorithm final : public puppet_master::runtime::Component {
public:
puppet_master::runtime::ComponentSpec Describe() const override;
puppet_master::core::Status Configure(
puppet_master::runtime::ComponentContext& context) override;
puppet_master::core::Status Execute(
puppet_master::runtime::ComponentContext& context) override;
};The lifecycle is explicit:
created -> configured -> initialized -> started -> stopped -> shutdown
Execute() is only valid after the component has started. A failed lifecycle
callback moves the component to error.
ComponentContext is passed into lifecycle callbacks. It lets a module create
readers and writers from its declared endpoints:
auto writer = context.CreateWriter(spec_.writers.front());
auto reader = context.CreateReader(spec_.readers.front());This keeps algorithm code independent from concrete transports. The same module can use in-memory transport in tests and a DDS-backed transport later, as long as the endpoint spec selects the desired backend.
RuntimeContext::RegisterComponent(ComponentPtr) stores both:
- the component declaration returned by
Describe() - the component instance and its current state
The older RegisterComponent(ComponentSpec) path still exists for pure
declarative registration, but lifecycle operations require a real component
instance.
The scheduler layer builds on this model by reading registered component specs,
observing their triggers, and calling ExecuteComponent() when a component
becomes ready. Component code still only implements lifecycle callbacks and
Execute(); it does not need to know which scheduler policy triggered it.