Add sub state machines and the materialized Part 16 model to the StateMachines sample - #860
Merged
Merged
Conversation
…eMachines sample (#829) The sample was written against 2.0.0-preview.2, whose fluent builder materialized no state or transition nodes and could not attach a sub state machine to a state. preview.4 does both, so the two parts issue #829 deferred can be built. Server: the Operation machine now carries a Production sub state machine below its Running state - Loading (initial), Processing and Unloading, with StartBatch as a cause of the child and the rest of the batch on the child's own timers. The framework activates and resets it when the parent enters Running and suspends it when the parent leaves. The states, transitions, their numbers and the Part 16 references are materialized by the builder, so the server code only declares the machine. Client: the window lists the model of the machine - a row per state and per transition with its number and NodeId - read through GetAvailableStatesAsync and GetAvailableTransitionsAsync, finds the sub state machine with GetSubStateMachineAsync on the state node it hangs off, and watches the Operation machine through ObserveEffectiveStateAsync so a transition of the parent or of the child is reported as one combined snapshot. The cause of the child is offered only while the child is active, which is what its Executable attribute says. Tests: the browse shape assertion covers the new children; new cases hold the machine to AvailableStates / AvailableTransitions in declaration order with the declared numbers, to the FromState / ToState / HasCause / HasEffect references of a transition, to HasSubStateMachine hanging off the state node rather than the machine root, to Bad_StateNotActive and BadNotExecutable while the child is suspended, and to a batch running to completion and starting over on re-entry. The tier 2 client case checks the model list, the cause becoming executable and the displayed sub state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
romanett
added a commit
that referenced
this pull request
Sep 4, 2026
Master extended four of the clients this branch had already split, so their new features are ported into the models rather than back into the windows: - RoleManagement (#864): the identity criteria (UserName/Thumbprint/X509Subject) and the criteria strings this client can be matched by, the CustomConfiguration flag, the AccessRestrictions and Endpoints columns, and the audit trail stream all live in RoleManagementClientModel; the window renders them. - StateMachines (#860): the materialized Part 16 model (available states and transitions), the sub state machine below Running with its StartBatch cause, and the effective state stream live in StateMachinesClientModel. - NodeManagement: the hand written model change pump is replaced by the stack's ModelChangeTracker inside the model. - UserAuthentication: the Kerberos and SAML stubs are gone from the model and the window, as on master. The model fixtures gained cases for the new surface; the testing guide keeps the model fixture column with master's updated StateMachines row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Proposed changes
The StateMachines sample was written against
2.0.0-preview.2, whose fluent builder materialized no state or transition nodes and could not usefully attach a sub state machine to a state.2.0.0-preview.4does both, so the two parts issue #829 deferred can now be built.Server (
Workshop/StateMachines/Server/StateMachinesNodeManager.cs)Operationmachine gains aProductionsub state machine below itsRunningstate, in the sample's own namespace:Loading(initial) →Processing→Unloading→Loading, withStartBatchas a cause of the child and the rest of the batch on the child's own timed transitions. The framework activates the child and resets it toLoadingwhen the parent entersRunningand suspends it when the parent leaves — declared withpreserveOnReentry: false, and the remarks say whattruewould do instead.StateTypenode per state carryingStateNumber(the initial one anInitialStateType), aTransitionTypenode per transition carryingTransitionNumberand the §4.4.11FromState/ToState/HasEffectreferences, theHasCausereference eachWithCauseadds, and theAvailableStates/AvailableTransitionsproperties.CurrentState/Idnow names a node a client can browse to.Client (
Workshop/StateMachines/Client/MainForm.cs)GetAvailableStatesAsync/GetAvailableTransitionsAsyncrather than browsed by hand.GetSubStateMachineAsyncon each state node is how the client findsProduction— off the state node per §4.4.16, not by browse name.Operationmachine is watched throughObserveEffectiveStateAsync, so a transition of the parent or of the child is reported as one combined snapshot and a row readsRunning / Processing. TheProgrammachine keepsObserveFiniteTransitionsAsync, which is the contrast worth showing.Production statefield shows the child, including theBad_StateNotActiveit reports while suspended, and aStartBatchbutton is offered only while the child's cause is executable.Related Issues
Types of changes
Checklist
Further comments
Tests. The existing browse shape assertion covers the new children of the machine. Five new cases in
StateMachinesNodeManagerTestshold the sample toAvailableStates/AvailableTransitionslisting exactly the nodes below the machine in declaration order with the declared numbers, to theFromState/ToState/HasCause/HasEffectreferences of a transition, toHasSubStateMachinehanging off the state node and not off the machine root, toBad_StateNotActiveandBad_NotExecutablewhile the child is suspended, and to a batch running to completion on the child's timers and starting over when the parent re-entersRunning. The tier 2 case inWorkshopClientSubscriptionTestsnow also checks the model list, the child's cause becoming executable once the machine is started, and the sub state the window shows.Locally:
StateMachinesNodeManagerTests15/15,WorkshopClientSubscriptionTests7/7, whole solution builds without new warnings.Two things a reviewer may want to know about the child machine. Its cause method has to be added after reading
.StateMachineinsideconfigure— that read is what freezes the child and creates the node the method hangs on. And a child is activated throughSetState, which runs no dispatcher synchronization, so no timed transition is armed out of the child's initial state; the child's first move is therefore a cause (StartBatch) and only the later transitions are timed. A timer left armed when the parent leaves is harmless:DoTransitionis refused withBadStateNotActive, and after the reset the from-state no longer matches.🤖 Generated with Claude Code