Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common.DataModel/StateMachines.md
2026-04-17 14:55:32 -04:00

121 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common.DataModel/StateMachines/OverallArmStatusStateMachine.cs
generated_at: "2026-04-16T03:32:13.517351+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "8fbd8ac85721cb74"
---
# StateMachines
## Documentation: `OverallArmStatusStateMachine`
---
### **1. Purpose**
The `OverallArmStatusStateMachine` class implements a state machine that tracks and manages the high-level operational status of an arm subsystem (likely related to data acquisition or recording hardware) within the DTS system. It uses the `Stateless` library to define transitions between states such as `Recording`, `IDLE`, `WaitingForTrigger`, `Downloading`, and `Disarmed`, based on triggers like `Recording`, `DoneRecording`, `Disarm`, and `DASNotFound`. Its primary role is to maintain a canonical "overall arm status" state, emit notifications on state changes via the `OverallStatusStateChange` event, and serve as a central coordination point for status reporting across the application (e.g., updating a global status UI field). It does *not* manage low-level arm logic but aggregates and reflects higher-level transitions.
---
### **2. Public Interface**
#### **Constructor**
```csharp
public OverallArmStatusStateMachine()
```
- Initializes the `IEventAggregator` via `ContainerLocator.Container.Resolve<IEventAggregator>()`.
- Calls `Initialize()` to configure the underlying `Stateless.StateMachine`.
#### **Events**
```csharp
public event OverallStatusStateChangeDelegate OverallStatusStateChange;
```
- **Delegate**: `public delegate void OverallStatusStateChangeDelegate(ArmStateMachineStates.States previousState, ArmStateMachineStates.States nextState);`
- Fired whenever the overall status transitions to a new state (i.e., `CurrentOverallStatusState` changes). The event includes the previous and next state.
#### **Methods**
```csharp
public ArmStateMachineStates.States GetDASStatus()
```
- Returns the current overall status state (`CurrentOverallStatusState`).
```csharp
public void FireTrigger(Triggers trigger, ArmStateMachineStates.States state)
```
- Fires a named trigger with an associated *target state parameter* (note: this is unusual—see *Gotchas*).
- Internally maps each `Triggers` enum value to a pre-configured `TriggerWithParameters<ArmStateMachineStates.States>` and invokes `StateMachine.Fire(trigger, state)`.
- Logs exceptions via `APILogger.Log(ex.Message)`; does *not* rethrow.
- **Special case**: `Triggers.PostTestProcessing` incorrectly fires `DoneRecordingTrigger` instead of a dedicated `PostTestProcessingTrigger`.
#### **Nested Types**
- `public enum Triggers`: Defines 37+ named triggers (e.g., `Recording`, `Disarm`, `DASNotFound`, `Downloading`, `WaitingForTrigger`, `WaitingForSchedule`, `WaitingForInterval`, `ReadyForDownload`, `DoneRecording`, `NoDataToDownload`, `DataNeverDownloaded`, `Streaming`, `FlashClear`, `Error`, `GettingEventInfo`, `CheckingForData`, `Rearming`, `IDLE`, `IntervalRecording`, `NonIntervalRecording`, `RunButton`, `a`, `c`, `d`, `e`, `h`, `n`, `rr`, `tt`, `uu`, `yy`).
- *Note*: Several triggers (`a`, `c`, `d`, `e`, `h`, `n`, `rr`, `tt`, `uu`, `yy`) appear to be placeholder or legacy names with no documented purpose.
---
### **3. Invariants**
- **Initial State**: The state machine always starts in `ArmStateMachineStates.States.CheckingForDAS`.
- **Current State Tracking**: `CurrentOverallStatusState` is updated *only* via `SetOverallStatus()`, which:
- Compares `newState` to `CurrentOverallStatusState`.
- Logs transitions via `APILogger.Log(...)`.
- Invokes `OverallStatusStateChange` *only if* the state changes.
- **State Machine Library**: Uses `Stateless.StateMachine<ArmStateMachineStates.States, Triggers>`.
- **Parameterized Triggers**: All transitions that accept a state parameter use `SetTriggerParameters<ArmStateMachineStates.States>()`, meaning every trigger expects a *target state* as an argument when fired (e.g., `Fire(trigger, targetState)`).
- **No Explicit Error Handling in Transitions**: Transitions do not define custom `OnEntryFrom`/`OnExit` logic beyond calling `SetOverallStatus()`; no fallback or recovery behavior is defined in the state configuration.
---
### **4. Dependencies**
#### **Imports/Usings**
- `Stateless` Core state machine library.
- `Prism.Ioc.ContainerLocator` For resolving `IEventAggregator`.
- `DTS.Common.Enums.TSRAIRGo` Provides `ArmStateMachineStates.States` (not shown in this file).
- `DTS.Common.Utilities.Logging` Provides `APILogger`.
- `System` and `Prism.Events` For `IEventAggregator`.
#### **External Dependencies**
- **`ArmStateMachineStates.States`**: An external enum defining the valid states (e.g., `CheckingForDAS`, `IDLE`, `Recording`, `Disarmed`, `Downloading`, `ClearingFlash`, `WaitingForTrigger`, `WaitingForSchedule`, `WaitingForInterval`, `PostTestProcessing`, `GettingEventInfo`, `ReadyForDownload`, `Streaming`). Its definition is not included here.
- **`APILogger`**: Static logging utility.
- **`ContainerLocator`**: Prism DI container accessor (assumes `IEventAggregator` is registered).
#### **Consumers**
- Any component needing to update or query the overall arm status (e.g., UI, telemetry, control logic) must:
- Subscribe to `OverallStatusStateChange` to react to state changes.
- Call `FireTrigger()` to signal events.
- Call `GetDASStatus()` to poll the current state.
---
### **5. Gotchas**
- **Unusual Trigger Signature**: All triggers are defined as `TriggerWithParameters<ArmStateMachineStates.States>`, meaning every `Fire()` call *must* supply a target state (e.g., `Fire(RecordingTrigger, ArmStateMachineStates.States.Recording)`). This is atypical—most state machines infer the next state from the transition configuration. The comment in `FireTrigger()` ("why specify state here? shouldn't that be done based on current state/trigger?") confirms this design is questionable and likely error-prone.
- **Incorrect Trigger Mapping**: In `FireTrigger()`, `Triggers.PostTestProcessing` incorrectly fires `DoneRecordingTrigger` instead of a dedicated `PostTestProcessingTrigger`. This may cause unintended state transitions (e.g., skipping `PostTestProcessing` state entirely).
- **Unused Triggers**: The `Triggers` enum includes 10 cryptic triggers (`a`, `c`, `d`, `e`, `h`, `n`, `rr`, `tt`, `uu`, `yy`) with no corresponding configuration in `Initialize()`. These are likely legacy or placeholders and should be removed or documented.
- **No Handling for `ErrorTrigger`**: While `ErrorTrigger` is declared, it is *not* used in any state configuration (no `.Permit()` or `.OnEntryFrom()` references it). Attempting to fire it will throw a `Stateless` exception (trigger not defined for current state).
- **Ignored Triggers May Cause Silent Failures**: Several states use `.Ignore()` for specific triggers (e.g., `ClearingFlash` ignores `ReadyForDownload`, `NoDataToDownload`, `DataNeverDownloaded`). Firing these triggers in those states will throw an exception (not silently ignored), contradicting the intent of `.Ignore()` in `Stateless` (which *does* allow the trigger but prevents transition). Verify `Stateless` behavior—this may be a source of runtime exceptions.
- **No Public Setter for State**: The current state is read-only via `GetDASStatus()`. There is no way to manually override or reset the state machine (e.g., for testing or recovery), which may complicate error recovery.
- **Logging Side Effect**: `SetOverallStatus()` logs *every* transition, which may be excessive in high-frequency scenarios. No filtering or throttling is applied.
- **Missing State Definitions**: The states used (e.g., `ArmStateMachineStates.States.CheckingForDAS`) are referenced but not defined in this file. Their semantics and relationships depend on the external `ArmStateMachineStates.States` enum.
- **No Validation on State Parameter**: `FireTrigger()` accepts any `ArmStateMachineStates.States` as the second parameter. Passing an invalid or inconsistent state (e.g., `Fire(RecordingTrigger, ArmStateMachineStates.States.Disarmed)`) may result in runtime exceptions or undefined behavior.
- **Exception Swallowing**: `FireTrigger()` catches and logs *all* exceptions (including `Stateless` exceptions like `InvalidOperationException` for invalid transitions), but does not propagate them. This can mask critical failures.
- **No Thread Safety**: The class does not indicate thread-safety. Concurrent calls to `FireTrigger()` or state queries may cause race conditions.
- **Graph Generation Side Effect**: `Stateless.Graph.UMLDotGraph.Format(...)` is called but the result is discarded (`string graph = ...; graph = ...;`). This suggests debugging code was left in place.
---
*Documentation generated from source file `Common/DTS.Common.DataModel/StateMachines/OverallArmStatusStateMachine.cs`.*