Reference Tree
The Reference Tree semantic module marks entity references that form
parent-child relationships. A scope-ref applies both the reference-target and
reference-tree constraints. The parser validates all scoped references together
as one or more trees. Entities without a parent are roots, and each root starts
a separate tree.
Why is a target type required?
A type-erased ref cannot form part of the
Reference Tree. A scope-ref must name its target entity type so Quent can
validate the parent relationships when it processes the schema.
Without a declared target type, different instances of the same child entity type could refer to different parent entity types at runtime. The generated instrumentation API could then no longer guarantee that the resulting relationships form the trees declared by the schema.
This gives analysis tools a preferred path from each root entity to its related entities and their events. In the model below, a task points to the pipeline that contains it. A user interface can open one pipeline and list its tasks, while analysis can associate each task’s events with that pipeline. Other tools can use the same hierarchy for their own purposes.
YAML model
quent: '0.1.0'
model: scoped_references
entities:
Pipeline:
events:
created: {}
Task:
events:
started:
attributes:
parent: { scope-ref: Pipeline }
ended: {}
Instrumentation API
The parent entity’s handle provides the reference. The additional hierarchy meaning belongs to the model and its constraints.
use instrumentation::{Context, Noop, Pipeline, ScopedReferences, Task};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let context = Context::<ScopedReferences>::try_new(Noop)?;
let mut pipeline = context.observer::<Pipeline>().handle();
pipeline.created()?;
let mut task = context.observer::<Task>().handle();
task.started(pipeline.as_entity_ref())?;
task.ended()?;
Ok(())
}
#include "quent-tutorial-scoped-references-cpp-bridge/gen/quent.hpp"
int main() {
auto context = quent::Context::none();
auto pipeline = context.pipeline_observer()->handle();
pipeline.created();
auto task = context.task_observer()->handle();
task.started(quent::task::Started{.parent = pipeline.id()});
task.ended();
return 0;
}
import quent_tutorial_scoped_references as quent
def main() -> None:
with quent.Context() as context:
pipeline = context.pipeline_observer().handle()
pipeline.created()
task = context.task_observer().handle()
task.started(parent=pipeline)
task.ended()
if __name__ == "__main__":
main()
A scoped reference defines a parent relationship in a validated entity tree.
Analysis
Quent’s analysis library provides a tree builder. Given entity instances and their parent IDs, it connects them into a tree and checks their relationships. The builder requires one root instance per input collection. A model with several roots can be analyzed one tree at a time.