74 lines
2.8 KiB
Markdown
74 lines
2.8 KiB
Markdown
# State Machine Instance Identification & Persistence Mapping
|
|
|
|
## 1. The Multi-SM Problem
|
|
In large applications, multiple State Machines often coexist. A "Trigger Point" (like a REST Controller) must be linked to the correct State Machine definition.
|
|
|
|
**Common Identification Patterns**:
|
|
- **Unique Types**: `StateMachine<OrderState, OrderEvent>` vs `StateMachine<UserState, UserEvent>`.
|
|
- **Bean Qualifiers**: `@Qualifier("orderStateMachine")`.
|
|
- **Factory IDs**: `factory.getStateMachine("order-123")`.
|
|
- **Persistence Restoration**: `persister.restore(sm, orderId)`.
|
|
|
|
## 2. Analysis Strategy: "Instance Tracking"
|
|
|
|
### 1. Definition Discovery (Existing)
|
|
Identify all configurations (classes with `@EnableStateMachineFactory` or `@EnableStateMachine`). Store their **Bean Names** and **Generic Types**.
|
|
|
|
### 2. Dependency Analysis
|
|
When a class (e.g., `OrderController`) uses a state machine:
|
|
1. **Identify the Field/Parameter**: Look for `StateMachine<S, E>`.
|
|
2. **Resolve Generic Types**: Match `S` and `E` against known SM definitions.
|
|
3. **Resolve Qualifiers**: Check for `@Qualifier` or variable names that match a SM bean name.
|
|
|
|
### 3. Loading & Persistence Analysis
|
|
A dedicated "Loading Detector" will look for persistence logic.
|
|
|
|
**Pattern: Persister Restore**
|
|
```java
|
|
persister.restore(stateMachine, id);
|
|
stateMachine.sendEvent(E);
|
|
```
|
|
**Static Strategy**:
|
|
- Find calls to `Persister.restore(sm, ...)` or `PersistStateChangeListener`.
|
|
- Link the variable `sm` to the restoration event.
|
|
- Mark the `TriggerPoint` as "Restored from Persistence".
|
|
|
|
**Pattern: Factory Creation**
|
|
```java
|
|
StateMachine sm = factory.getStateMachine(smId);
|
|
```
|
|
**Static Strategy**:
|
|
- Find `factory.getStateMachine(...)`.
|
|
- If the argument is a literal (e.g., `"order"`), map it to the SM definition named "order".
|
|
|
|
## 3. Implementation: `InstanceIdentifier`
|
|
We will introduce an `InstanceIdentifier` that works alongside the `ValueResolver`.
|
|
|
|
```java
|
|
public class InstanceIdentifier {
|
|
public StateMachineReference identify(VariableDeclaration var, CodebaseContext context) {
|
|
// 1. Check type generics
|
|
// 2. Check @Qualifier
|
|
// 3. Trace back to factory or persister calls
|
|
}
|
|
}
|
|
```
|
|
|
|
## 4. Modeling in `AnalysisResult`
|
|
The `TriggerPoint` will be enhanced with a `stateMachineId` or `configFqn` field.
|
|
|
|
```java
|
|
public record TriggerPoint(
|
|
String className,
|
|
String methodName,
|
|
String event,
|
|
String stateMachineId, // Links back to the specific SM
|
|
boolean isRestoredFromPersistence,
|
|
Map<String, String> metadata
|
|
) {}
|
|
```
|
|
|
|
## 5. Challenges
|
|
- **Generic Controllers**: A single base controller that handles multiple SMs via generics. We might need to report "Multiple Potential SMs".
|
|
- **Dynamic Factory IDs**: `factory.getStateMachine(payload.getType())`. Hard to resolve statically without data flow analysis.
|