Skip to content

feat(instrumentation-build): generate namespaced instrumentation APIs - #450

Closed
johanpel wants to merge 5 commits into
rapidsai:mainfrom
johanpel:instrumentation-type-paths
Closed

feat(instrumentation-build): generate namespaced instrumentation APIs#450
johanpel wants to merge 5 commits into
rapidsai:mainfrom
johanpel:instrumentation-type-paths

Conversation

@johanpel

@johanpel johanpel commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Description

Schema type paths were added in #449, but quent-instrumentation-build temporarily rejected paths with more than one segment.

Flattening paths into Rust identifiers loses segment boundaries. For example, these distinct schema paths:

Foo::BarBaz
FooBar::Baz

would both become FooBarBaz. This PR instead preserves the schema structure using Rust modules:

foo::BarBaz
foo_bar::Baz

Equal leaf names can therefore coexist naturally:

foo::Query
bar::Query

Generated records, entity markers, event types, reference targets, handle implementations, and AnyEvent enums follow the same module structure. Entity stream names retain the complete schema path, and namespace-local AnyEvent enums compose into their parents.

Generated instrumentation API

Previously, every entity generated separately named observer and handle types, which could conflict with valid schema types such as QueryObserver or QueryHandle:

pub struct ServerObserver { /* ... */ }
pub struct ConnectionObserver { /* ... */ }

pub struct ServerHandle { /* ... */ }
pub struct ConnectionHandle { /* ... */ }

pub struct DemoContext { /* ... */ }

The API now uses shared Context and Observer types from quent-instrumentation, plus one generated generic Handle and schema marker types:

pub struct Demo;
pub struct Handle<E> { /* ... */ }

pub use quent_instrumentation::{Context, Observer};

Qualified entity paths are used directly as type arguments:

let context: Context<Demo> = Context::try_new(exporter)?;
let observer: Observer<foo::Query> = context.observer::<foo::Query>();
let handle: Handle<foo::Query> = observer.handle();

Generated typed observer collections mirror the schema namespace hierarchy. Compile-time ObserverAccess<E> implementations map each entity to its stored observer without flattened identifiers, runtime downcasts, or tuple indices.

Shared context and observer behavior, along with handle state and emission mechanics, now lives in quent-instrumentation. The generated API retains only schema-dependent markers, event enums, observer collections, and event methods. Each context owns exactly one ObserverInner transport per entity type, shared by that entity’s observer and handles.

Overview of the instrumentation types / traits

Not generated

Item Kind Purpose
Context<M> Struct Public context for one model instance; owns the model’s observers and runtime context.
Observer<E> Struct Public entity-level factory for creating typed handles.
Model Trait Connects a model marker to observer construction and model metadata.
ContextInner Struct Hidden runtime and context-ID backing for Context<M>.
Entity Trait Associates an entity marker with its event, context, and handle types.
ObserverInner<T> Struct Hidden shared event transport and exporter lifecycle.
ObserverAccess<E> Trait Provides compile-time access to the stored Observer<E>.
HandleInner<E> Struct Hidden entity-instance state: UUID, once-event flags, and observer transport.
EventSender<T> Struct Clonable event producer that does not own the observer lifecycle.
HandleError Enum Reports handle emission errors such as repeated once-events.

Generated

Item Kind Purpose Why generated
{Model} Struct Type-level model marker. Its identity and metadata come from the schema.
impl Model for {Model} Trait implementation Constructs observers and supplies model metadata. Construction and metadata depend on the schema.
{Model}Observers Struct Root observer collection. Its fields mirror the schema’s root entities and namespaces.
{Namespace}Observers Struct Observer collection within {Namespace}. Its fields mirror that namespace’s entities and child namespaces.
impl ObserverAccess<{Namespace}::{Entity}> for {Model}Observers Trait implementation Maps an entity type to its observer field. The storage path follows the schema namespace hierarchy.
{Namespace}::{Entity} Struct Type-level entity marker. Its identity comes from the schema path.
impl Entity for {Namespace}::{Entity} Trait implementation Associates the entity with its event, context, and handle. Those associations depend on the generated model.
impl Handle<{Namespace}::{Entity}> Inherent implementation Provides named event-emission methods. Methods, parameters, and cardinalities come from the schema.
{Namespace}::{Entity}Event Enum Represents the entity’s declared events. Variants and fields come from the schema.
Handle<E> Struct Public model-specific handle wrapper. It must live in the generated crate to receive entity-specific inherent methods.
{Namespace}::AnyEvent<'a> Enum Decodes type-erased events within a namespace. Variants mirror its entities and child namespaces.

Related Issues

Follow-up to #449. Closes #442.

Written by Codex.

johanpel added 2 commits July 24, 2026 15:26
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
Signed-off-by: Johan Peltenburg <johan.peltenburg+code@gmail.com>
@johanpel johanpel changed the title Instrumentation type paths feat(instrumentation-build): generate namespaced instrumentation APIs Jul 24, 2026
johanpel added 3 commits July 24, 2026 15:52
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

Copy link
Copy Markdown
Contributor Author

Closing this to split out over PRs:

#466
#467
#468

@johanpel johanpel closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce namespacing paths for record and entity types in the schema

1 participant