feat(query): state and event queries over a session, and a page telling the query kinds apart - #359
Merged
Merged
Conversation
Which query is which distinguishes document queries (element, object and verdict rows), the API Query and OSLC text, Evaluate, the runtime extent all T and solve: what each reads, returns and cannot see. The reference pages that restated a boundary now point at it. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…s from Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ade by Co-Authored-By: jason.han <hanhuijun@gmail.com>
…untime and trace Co-Authored-By: jason.han <hanhuijun@gmail.com>
…clients, the renderers and -run-query State and event rows gain arms of DocumentValue, so RunDocumentQuery reports them and the Go, Python, Java, TypeScript and Rust clients decode them; the Markdown, HTML and PDF renderers print a state as "object.machine in state" and an event as its timed trace line. -run-query now runs after the behaviors named, so a state query reads where -advance left a machine and an event query reads what -trace recorded. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…e and event queries Regenerates the library snapshot for the States, InState and Events operations DocumentQueries declares, and documents the -run-query ordering after -state, -action and -advance. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…y code Co-Authored-By: jason.han <hanhuijun@gmail.com>
…; bound the events a served population keeps Send records carry the action or state machine that sent, so an Events row over a send answers `machine` and its behavior-declared properties; a message posted from outside the run names no behavior. Choices and unevaluable guards an action draws are recorded as the performer's under the action, so an Events query bound to a source sees them beside the state machine's; the scheduler's run-wide draws stay unattributed. sysml-grpc gives each cached population a query-only recorder bounded by OPENSYSML_GRPC_MAX_HELD_EVENTS (default 100000): the oldest records are dropped as newer ones arrive, and an Events query whose interval reaches dropped history fails with `trace-truncated` (FAILED_PRECONDITION) rather than answer from a partial trace. RecordAcceptAt places by whole-run mark so a late accept lands where it belongs after trimming. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…truncation in snapshots A state row's region is the innermost orthogonal region an enclosing state is declared in, found by walking the parent chain as the executor does, so a leaf nested below a region's own state no longer reads as outside every region. A snapshot of a bounded trace recorder now captures how many records it had dropped and up to when, and restores them with the records, so an Events query after a restore is not refused for history the explored branch discarded. Trimming cuts the record slice from the front instead of shifting in place, so the slice a snapshot holds still reads what it did at the mark. Co-Authored-By: jason.han <hanhuijun@gmail.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Two parts, both about queries.
A page telling the query kinds apart.
docs/manual/query-kinds.mdplaces the project's query surfaces side by side — document queries over elements, object rows, verdict rows, state rows and event rows; the APIQueryand its OSLC text;Evaluate;solve; the runtime populationall Tand the collection operations over it — saying what each returns, what each cannot see, and which to reach for. The pages that re-explained the boundary (manual/introduction.md,manual/query-cookbook.md,reference/api.md,reference/oslc-query.md) now point at it;reference/cli.mdandreference/repl-commands.mddocument the new rows where they document-run-queryand%run-query.State and event queries over a session. Three document-query operations in
DocumentQueries, besideObjectsandVerdicts, refused with a typed error outside a session asObjectsis:States(source)— one row per active leaf state of each source object's machine, every orthogonal region, with the composite states enclosing the leaf.InState(name)— the objects the session holds whose machine is in that state, by leaf name, enclosing name or dotted path (on.run); object rows, soWhereType,Projectand the rest apply.Events(source, kind, since, before)— the run's trace as a relation in the order recorded: accepts, sends, transitions fired, entry/exit/do steps, choice draws (due-order draws included) and unevaluable guards, filtered by object, by kind and by the interval[since, before).The trace they read is the runtime's own record.
runtime.TraceRecordernow keeps typedTraceRecords and prints-trace's lines from them (TraceRecord.Line), so the printed trace and theEventsrows cannot drift; every-tracegolden is byte-identical.Clearmarks records printed rather than dropping them, so a query reads the whole run while each drain prints only what is new.Every record names the object and the behavior that made it: an action's sends, choice draws and unevaluable guards are the performer's under the action, a state machine's are under the machine, and a message posted from outside the run names neither.
sysml-grpcgives each cached population a query-only recorder bounded byOPENSYSML_GRPC_MAX_HELD_EVENTS(default 100000,docs/reference/environment.md): the oldest records are dropped as newer ones arrive, and anEventsquery whose interval reaches dropped history fails with the typedtrace-truncatederror (FAILED_PRECONDITION) rather than answer from a partial trace.-run-querynow runs after-state,-actionand-advance, so a state query reads where the run left the machine and an event query reads what it recorded — before, it ran on the initial state and an empty trace.Row and value design
A row is a value that
Value.isRowadmits;Project,WhereFeature,OrderByandColumnread its properties throughpropertyValues. Two row kinds joinValueObjectandValueVerdict; the object column of both reusesqueryexec.ObjectValue, so an object projected from a state row is the object row the session prints and crossesRunDocumentQueryas the existingDocumentValue.objectarm.State row (
queryexec.State,ValueState; properties declared onDocumentQueries::State):objectElement[1]ObjectValue(inst, label)pathString[1]#1.lp,Garage::car.engine)machineString[1]Cookbook::dome.control)nameString[1]statePathString[1]open.slewing)stateElement[0..1]regionString[1]enclosingString[0..*] orderedA row also answers its state declaration's own properties. Label:
lamp1.lp in on.dim. An object with no state machine isErrorNoStateMachine; an element row that declares no held object isErrorNotHeld; a state row given to a model-only operation isErrorStateRow; a state no machine declares isErrorUnknownState.Event row (
queryexec.Event,ValueEvent; properties onDocumentQueries::Event):kindString[1]accept,send,transition,entry,exit,do,choice,guardtimeScalarValue[1]objectElement[0..1]ObjectValue; absent for a behavior run without onepathString[0..1]machineString[0..1]stateString[0..1]from,toString[0..1]targetElement[0..1]eventString[0..1]payloadString[0..*] orderedname = valueper featurealternativesString[0..*] orderedtakenString[0..1]textString[1]A row also answers the properties of the behavior that made it. Summary:
t=1 lamp1.lp: accept Dim.sinceandbeforetake a duration (1 [s],500 [ms], converted through the clock's unit asafterandatare) or a bare number of the clock's seconds, either left open; the interval is inclusive ofsinceand exclusive ofbefore. A bound that is no instant on the clock (1 [m]), orbefore <= since, isErrorInvalidInterval; a kind the trace does not record isErrorInvalidArgument; a session recording no trace isErrorNoTrace; no session isErrorNoRuntime; an event row given to a model-only operation isErrorEventRow.Wire shape.
DocumentValuegains two answer-only arms,state(DocumentState) andevent(DocumentEvent), mirroring the two tables;DocumentQueryRowcarries them besideobjectandverdict. Binding either is refused like a verdict. The Go and Python clients decode them (Row.State,Row.Event;DocumentState,DocumentEvent) and refuse to bind them; the Java, TypeScript and Rust generated code is regenerated.Rendering. Markdown prints a state row as
<object>.<machine> in <statePath>and an event row ast=<instant> <object>.<machine>: <text>; HTML wraps them inspan.sysml-state(data-machine,data-state,data-region) andspan.sysml-event(data-event-kind,data-time); the PDF backend lays out the Markdown.Specification basis
Non-normative OpenSysML document-query vocabulary (
DocumentQueries); the states read are the SysML v2 state configurations as the state executor holds them (KerML/SysML v2 §7.20, active states across orthogonal regions), the trace the runtime's own record.docs/project/spec-compliance.mdgains three rows under document-query execution: the state operations, the typed trace andEvents, and the rendering, API and client surface.How it was verified
New tests, all passing:
internal/core/queryexec/states_test.go,events_test.go— each operation and filter over a fixture with two lamps in different states and a trace with accepts, sends, transitions, entry/exit/do steps, choices and guards; the[since, before)boundary; every refusal.internal/core/runtime—-tracegoldens byte-identical; trace-record tests.internal/core/docrender/states_test.gowithtestdata/state_report.sysmland its Markdown/HTML goldens;internal/docpdflayout golden and the WeasyPrint and Pandoc PDF renders run with the toolchain provisioned (Prince absent, skipped).internal/grpc/testdata/conformance/document_query_{states,in_state,events}conformance cases;client/opensysml/states_test.go;clients/python/tests/test_document.py(35 passed).internal/repl/docquery_states_test.go,internal/repl/cookbook_states_test.go(the cookbook recipes, driven as the cookbook drives them);cmd/sysml/run_query_test.go(-run-queryafter-state/-advance, with and without-trace).Gates run locally on the merged branch:
Checked by hand at the prompt: the cookbook sequence (
%trace on, two domes,%send/%advance), the refusals for1 [m],before <= since, an unknown state, an object with no machine and a query with%trace off, andOrderBydescending over event time.Known limitations
None in the operations. Three boundaries, documented on the page: an event query sees the trace of its own session only (no cross-session queries); it reads records already made — a query does not see events the clock has not reached; and over
sysml-grpcit reads the most recentOPENSYSML_GRPC_MAX_HELD_EVENTSrecords, refusing an interval that reaches older ones.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)