elsa-workflows / elsa-workflows/elsa-core
State Machine Activity
- Dominant language
- C#
- Stars
- 7.9k
- Forks
- 1.5k
- Avg merge
- 15h 22m
- Merged PRs (30d)
- 114
Description
## Functional Description
The **State Machine activity** should be designed with the following features:
### **1. States and Transitions**
- Allows defining distinct **states** and **transitions** between them.
- Transitions should be based on specified **conditions** or **events**.
### **2. Triggers for Transitions**
- Transitions are driven by **triggers**.
- Like WF4, a transition contains two slots:
- **Trigger**: Holds any activity, including event-like activities such as **Delay, Event, or Message Received**.
- **Action**: Executes when the transition is triggered, after which the transition completes and the **target state** is entered.
### **3. Trigger Cancellation**
- Whenever a **transition occurs**, all **other outbound transitions are canceled**.
- Any **pending trigger activities** should also be **canceled**.
### **4. Entry and Exit Actions**
- Each state supports the execution of **actions** when:
- **Entering** the state → **Entry Action**
- **Exiting** the state → **Exit Action**
- These actions should be represented as **activities**, allowing full flexibility.
---
## **Technical Plan**
### **1. Server-Side Implementation**
#### **StateMachine Activity**
- Create the `StateMachine` activity class with:
- `States`: A **collection of `State` activities**.
- `CurrentState`: A **reference** to the currently active state.
- `InitialState`: A **reference** to the first state upon execution.
- `Transitions`: A **collection of `Transition` objects**.
#### **Execution Flow**
- When the **StateMachine** executes:
1. **Schedule** the current (or **initial**) State activity for execution.
2. **Schedule all Trigger activities** of outbound Transitions and observe their completions.
- When a **Transition's Trigger activity** completes:
1. **Evaluate the Transition’s Condition**:
- If **no condition** is set, treat it as `true`.
- If **true**, then:
- Schedule the **Transition's Action activity**.
- Clear any **bookmarks** created by the **Trigger activity**.
- **Cancel all other outbound Transitions**.
- If **false**, do nothing (retain the bookmark for future triggers).
- When a **Transition’s Action activity** completes:
1. **Schedule the Exit activity** of the **source state**.
2. **Schedule the Entry activity** of the **target state**.
---
### **2. Core Components**
#### **State Activity**
- Represents a **state** in the state machine.
- Properties:
- `Name`: **Identifies the state**.
- `Entry`: **Executes an activity when entering the state**.
- `Exit`: **Executes an activity when exiting the state**.
- **Execution Logic**:
- When first executed, the **Entry activity** runs.
#### **Transition Class**
- Represents a **transition** between states.
- Properties:
- `Name`: Identifier for the transition.
- `DisplayName`: A human-friendly name.
- `Trigger`: An `IActivity` representing the transition trigger.
- `Condition`: A **dynamic boolean input** to determine transition eligibility.
- `Action`: An `IActivity` representing the action to perform upon transition.
---
## **3. Sample JSON Representation**
This JSON structure represents how the `StateMachine` activity could be persisted in Elsa.
```json
{
"id": "stateMachine1",
"type": "StateMachine",
"initialState": "OrderProcessing",
"currentState": "PaymentProcessing",
"states": [
{
"name": "NewOrder",
"entry": { "type": "WriteLine", "text": "New Order Created" },
"exit": { "type": "WriteLine", "text": "Exiting New Order" }
},
{
"name": "PaymentProcessing",
"entry": { "type": "WriteLine", "text": "Processing Payment" },
"exit": { "type": "WriteLine", "text": "Payment Processed" }
},
{
"name": "Shipped",
"entry": { "type": "WriteLine", "text": "Shipping Order" },
"exit": { "type": "WriteLine", "text": "Order Shipped" }
}
],
"transitions": [
{
"name": "ProcessPayment",
"from": "NewOrder",
"to": "PaymentProcessing",
"trigger": { "type": "EventReceived", "eventName": "PaymentReceived" },
"condition": "Order.Amount > 0",
"action": { "type": "WriteLine", "text": "Processing Payment Transition" }
},
{
"name": "ShipOrder",
"from": "PaymentProcessing",
"to": "Shipped",
"trigger": { "type": "EventReceived", "eventName": "PaymentSuccessful" },
"action": { "type": "WriteLine", "text": "Processing Shipment Transition" }
}
]
}
````
### **Key Features in JSON**
- **States** contain `entry` and `exit` activities.
- **Transitions** specify:
- `from` → Source state.
- `to` → Target state.
- `trigger` → The event that causes the transition.
- `condition` → A dynamic condition for validation.
- `action` → The activity executed during transition.
---
## **4. UI & Designer Implementation**
### **1. State Machine Designer**
- Implement a **dedicated StateMachine designer**:
- Uses **X6 Graph library** for rendering.
- **Drag & drop interface** for defining states and transitions.
- **No source outcomes** (unlike Flowchart activities).
- Users can **connect** states via transitions.
### **2. Transition Editing UI**
- Each **transition** should be **editable** with:
- **Trigger:** A **designer canvas** for embedding an activity.
- **Condition:** A **dynamic expression input**.
- **Action:** A **designer canvas** for embedding an activity.
---
### **3. Designer Experience for Activities**
> **Current Issue**: Elsa Studio treats activity designers like **Flowchart** as **full-screen components**.\
> **Proposal**: Each activity should provide its **own designer experience**.
- When an activity **contains another activity** (e.g., a `Flowchart` inside a `Trigger` slot):
- The **Flowchart should be embedded** in its container, rather than taking the full screen.
- This enables **nested workflows** without disrupting the UX.
- **Example Use Case**:
- Dragging a **Flowchart** into the **Trigger slot** should embed a **Flowchart designer** in that slot.
- This allows complex **nested control flows**.
---
## **Total Estimated Time**
| Phase | Estimated Days |
|--------|----------------|
| **Core Backend Implementation** | 3-5 days |
| **Designer UI & UX Enhancements** | 15-22 days |
| - **Decoupling Flowchart-specific logic** | 10-15 days |
| - **Implementing StateMachine Designer** | 5-7 days |
| **Total Estimated Time** | **18-27 days (3-4 weeks)** |
---
## **Resources**
- [Building State Machine Workflows with Windows Workflow Foundation](https://www.youtube.com/watch?v=-1EN72EXtpU)
Contributor guide
Assessment
This issue has not been assessed yet.