elsa-workflows / elsa-workflows/elsa-core

State Machine Activity

Open
#5,085 7 comments 8 reactions 1 assignee Claimed by @sfmskywalker View on GitHub
triaged
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.