feat(schema): add paths for schema types - #449
Conversation
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
johanpel
left a comment
There was a problem hiding this comment.
Self-review to help reviewers
There was a problem hiding this comment.
Records and entities share one type namespace, enforced by builder validation and the new DuplicateTypePaths base constraint.
| #[cfg_attr(feature = "serde", serde(with = "indexmap::map::serde_seq"))] | ||
| #[cfg_attr(feature = "ts", ts(as = "Vec<(Path, Entity)>"))] | ||
| entities: Map<Path, Entity>, | ||
| /// The [`Record`]s of the model. | ||
| #[cfg_attr(feature = "ts", ts(as = "indexmap::IndexMap<Identifier, Record>"))] | ||
| records: Map<Identifier, Record>, | ||
| #[cfg_attr(feature = "serde", serde(with = "indexmap::map::serde_seq"))] | ||
| #[cfg_attr(feature = "ts", ts(as = "Vec<(Path, Record)>"))] | ||
| records: Map<Path, Record>, |
There was a problem hiding this comment.
- Schema record/entity maps serialize as entry sequences because paths are arrays.
Luckily this was already a feature of indexmap
| fn ensure_unqualified_type_paths(schema: &Schema) -> Result<(), GenerateError> { | ||
| let qualified = schema | ||
| .records() | ||
| .map(|record| record.path()) | ||
| .chain(schema.entities().map(|entity| entity.path())) | ||
| .find(|path| !path.namespace().is_empty()); | ||
|
|
||
| match qualified { | ||
| Some(path) => Err(GenerateError::UnsupportedTypePath { path: path.clone() }), | ||
| None => Ok(()), | ||
| } | ||
| } |
There was a problem hiding this comment.
instrumentation-build temporarily rejects qualified paths
This is temporary, follow-up will change this.
| /// Return the default usage record path for `resource`. | ||
| pub fn default_usage_record_path(resource: &Path) -> Path { | ||
| resource.with_name(suffixed_identifier(resource.name(), "Usage")) | ||
| } | ||
|
|
||
| /// Return the default bounds record name for `resource`. | ||
| pub fn default_bounds_record_name(resource: &Identifier) -> Identifier { | ||
| suffixed_identifier(resource, "Bounds") | ||
| /// Return the default bounds record path for `resource`. | ||
| pub fn default_bounds_record_path(resource: &Path) -> Path { | ||
| resource.with_name(suffixed_identifier(resource.name(), "Bounds")) | ||
| } |
There was a problem hiding this comment.
Foo::Memorygenerates sibling resource records such asFoo::MemoryUsage
| #[test] | ||
| fn generated_records_are_siblings_of_the_resource() { | ||
| let parts = ResourceBuilder::new(path("Foo::Memory")) | ||
| .with_capacity(ident("bytes"), Capacity::new(CapacityKind::Occupancy, true)) | ||
| .build() | ||
| .unwrap(); | ||
|
|
||
| assert_eq!(parts.usage.path().to_string(), "Foo::MemoryUsage"); | ||
| assert_eq!( | ||
| parts.bounds.unwrap().path().to_string(), | ||
| "Foo::MemoryBounds" | ||
| ); | ||
| } |
There was a problem hiding this comment.
Foo::Memorygenerates sibling resource records such asFoo::MemoryUsage
📝 WalkthroughWalkthroughThe schema model now uses qualified ChangesPath-based schema identity
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
| #[cfg_attr(feature = "serde", serde(try_from = "Vec<Identifier>"))] | ||
| #[cfg_attr(feature = "ts", derive(ts_rs::TS))] | ||
| #[cfg_attr(feature = "ts", ts(as = "Vec<Identifier>"))] | ||
| pub struct Path(Vec<Identifier>); |
There was a problem hiding this comment.
Maybe for a follow-up; split this into name and namespace (optional). That avoids the invalid empty vec.
There was a problem hiding this comment.
That turned out to simplify a few things 👍
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
|
/merge |
# Description Stacked on #466. Adds qualified schema type path support to `quent-instrumentation-build`. Schema namespaces become Rust modules instead of being flattened: ```rust Foo::BarBaz → foo::BarBaz FooBar::Baz → foo_bar::Baz ``` This preserves path boundaries and allows equal leaf names such as Foo::Query and Bar::Query to coexist. Records, entities, events, references, handles, and observer storage follow the generated module hierarchy. Namespace-local AnyEvent enums compose into their parent namespace, while namespaces without events generate no aggregate. ## Related Issues Follow-up to #449. Closes #442. _Written by Codex._ Authors: - Johan Peltenburg (https://github.com/johanpel) Approvers: - Dhruv Vats (https://github.com/dhruv9vats) URL: #468
Description
Add
quent_schema::Pathand migrate record and entity types from flat identifiers to paths. Most of the diff mechanically propagates that type change through constraints, FSMs, references, resources, and YAML lowering.The notable behavioral changes are:
Foo::Memorygenerates sibling resource records such asFoo::MemoryUsage.instrumentation-buildtemporarily rejects qualified paths.YAML syntax remains unchanged and only produces one-segment paths.
A follow-up PR will add namespaced Rust instrumentation generation and simplify the generated runtime API.
Related Issues
Extracted from #448 to make reviewing easier. Part of #442.
Written by Codex.