Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ The workflow engine is organized into 8 layers:
- `IFlowNode` - Interface defining node lifecycle methods
- `BaseFlowNode` - Abstract base for all nodes, manages actions and strategies
- `BaseAuditNode` - Abstract base for audit nodes (ApprovalNode, HandleNode)
- 11 node types: StartNode, EndNode, ApprovalNode, HandleNode, NotifyNode, ConditionBranchNode, ParallelBranchNode, RouterBranchNode, InclusiveBranchNode, DelayNode, TriggerNode, SubProcessNode
- 12 node types: StartNode, EndNode, ApprovalNode, HandleNode, NotifyNode, BranchNodeBranchNode, ParallelBranchNode, RouterBranchNode, InclusiveBranchNode, SubProcessNode, DelayNode, TriggerNode

3. **Action Layer** (`com.codingapi.flow.action`, `com.codingapi.flow.action.actions`)
- `IFlowAction` - Interface for node actions with `copy()` method
- `BaseAction` - Abstract base with `triggerNode()` for recursive traversal
- 8 action types: DefaultAction, PassAction, RejectAction, SaveAction, ReturnAction, TransferAction, AddAuditAction, DelegateAction, CustomAction
- 9 action types: DefaultAction, PassAction, RejectAction, SaveAction, ReturnAction, TransferAction, AddAuditAction, DelegateAction, CustomAction

4. **Record Layer** (`com.codingapi.flow.record`)
- `FlowRecord` - Execution record with states (TODO/DONE, RUNNING/FINISH/ERROR/DELETE)
Expand All @@ -100,6 +100,13 @@ The workflow engine is organized into 8 layers:
- `ScriptRuntimeContext` - Groovy script execution with thread-safe design and auto-cleanup
- Script types: OperatorMatchScript, OperatorLoadScript, NodeTitleScript, ConditionScript, ErrorTriggerScript, RejectActionScript

### Supporting Architectures

- **Repository Pattern** (`com.codingapi.flow.repository`) - Abstraction for data persistence, isolates framework from implementation
- **Gateway Pattern** (`com.codingapi.flow.gateway`) - Anti-corruption layer for external system integration (operators, users)
- **Backup System** (`com.codingapi.flow.backup`) - Workflow versioning and backup management
- **Error Handling** (`com.codingapi.flow.error`) - Centralized error throwing mechanism for flow control

### Node Lifecycle (Critical for Understanding Flow)

When a node is executed, methods are called in this order:
Expand Down Expand Up @@ -139,6 +146,8 @@ When encountering `ParallelBranchNode`:
- **Chain of Responsibility**: `triggerNode()` recursive traversal, `StrategyManager` strategy iteration
- **Composite**: Nodes contain multiple strategies and actions
- **Copy Pattern**: `INodeStrategy.copy()`, `IFlowAction.copy()`, `BaseFlowNode.setActions()`, `BaseFlowNode.setStrategies()`
- **Repository**: Abstracts data persistence, implementations in infra layer
- **Gateway**: Anti-corruption layer for external system integration

### Strategy-Driven Node Configuration (Critical Architecture)

Expand Down Expand Up @@ -200,6 +209,8 @@ Use framework exceptions instead of generic exceptions (IllegalArgumentException
- **Custom Strategies**: Extend `BaseStrategy`, implement `INodeStrategy`
- **Custom Scripts**: Use `ScriptRuntimeContext` for Groovy execution
- **Event Listeners**: Listen to `FlowRecordStartEvent`, `FlowRecordTodoEvent`, `FlowRecordDoneEvent`, `FlowRecordFinishEvent`
- **Repository Implementations**: Implement repository interfaces in infra layer for persistence
- **Gateway Implementations**: Implement gateway interfaces for system integration

## Documentation References

Expand Down
14 changes: 11 additions & 3 deletions Design.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
- `operatorCreateScript`: 创建者匹配脚本
- `isInterfere`: 是否开启干预
- `isRevoke`: 是否开启撤销
- `createdOperator`: 创建者ID
- `createdTime`: 创建时间
- `schema`: 流程版本标识
- **核心方法**:
- `verify()`: 验证流程定义的合法性
- `nextNodes(IFlowNode)`: 获取指定节点的后续节点
- `getStartNode()`: 获取开始节点
- `getEndNode()`: 获取结束节点
- `toJson()`: 序列化为JSON
- `formJson()`: 从JSON反序列化
- `formJson(String)`: 从JSON反序列化(静态方法)

#### WorkflowBuilder
- **位置**: `com.codingapi.flow.workflow.WorkflowBuilder`
Expand Down Expand Up @@ -70,7 +73,7 @@
- `isDone()`: 通过StrategyManager判断多人审批完成状态
- `generateCurrentRecords()`: 通过StrategyManager加载操作者并生成记录

#### 节点类型一览 (11种)
#### 节点类型一览 (12种)

| 节点类型 | 类名 | NODE_TYPE | 说明 |
|---------|------|-----------|------|
Expand Down Expand Up @@ -167,7 +170,12 @@
#### FlowAdvice
- **位置**: `com.codingapi.flow.session.FlowAdvice`
- **职责**: 封装审批操作的相关参数
- **核心属性**: `advice`(审批意见), `signKey`(签名), `action`(动作), `backNode`(退回节点), `transferOperators`(转办人员)
- **核心属性**:
- `advice`: 审批意见
- `signKey`: 签名
- `action`: 动作类型
- `backNode`: 退回节点(类型为 `IFlowNode`,节点对象引用)
- `transferOperators`: 转办人员列表

---

Expand Down
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,37 @@ flow-engine
│ ├── src/main/java
│ │ └── com.codingapi.flow
│ │ ├── action # 操作层
│ │ │ ├── actions # 具体操作实现
│ │ │ └── factory # 操作工厂
│ │ ├── backup # 流程备份
│ │ ├── builder # 构建器
│ │ ├── context # 上下文
│ │ ├── edge # 节点连线
│ │ ├── error # 错误处理
│ │ ├── event # 事件
│ │ ├── exception # 异常
│ │ ├── form # 表单
│ │ ├── gateway # 网关
│ │ ├── exception # 异常体系
│ │ ├── form # 表单系统
│ │ │ └── permission # 字段权限
│ │ ├── gateway # 网关接口防腐层
│ │ ├── node # 节点层
│ │ ├── operator # 操作人
│ │ │ ├── factory # 节点工厂
│ │ │ ├── helper # 节点辅助类
│ │ │ ├── manager # 节点管理器
│ │ │ └── nodes # 具体节点实现
│ │ ├── operator # 操作人接口
│ │ ├── pojo # 数据对象
│ │ ├── record # 记录层
│ │ ├── script # 脚本层
│ │ │ ├── body # 请求体
│ │ │ └── request # 请求对象
│ │ ├── record # 流程记录
│ │ ├── repository # 仓储接口
│ │ ├── script # 脚本系统
│ │ │ ├── action # 操作脚本
│ │ │ ├── node # 节点脚本
│ │ │ └── runtime # 脚本运行时
│ │ ├── service # 服务层
│ │ │ └── impl # 服务实现
│ │ ├── session # 会话层
│ │ ├── strategy # 策略层
│ │ ├── user # 用户
│ │ ├── utils # 工具类
│ │ └── workflow # 流程层
│ └── src/test/java # 测试代码
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ public int getParallelBranchTriggerCount(String parallelId) {
public void addParallelTriggerCount(String parallelId) {
parallelBranchRepository.addTriggerCount(parallelId);
}

public void clearParallelTriggerCount(String parallelId) {
parallelBranchRepository.clearTriggerCount(parallelId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ public boolean isDone(FlowSession session) {
@Override
public List<FlowRecord> generateCurrentRecords(FlowSession session) {

if (this.isWaitParallelRecord(session)) {
// 是否等待并行合并节点
if (this.isWaitRecordMargeParallelNode(session)) {
return List.of();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private void verifyDefaultConfig(){
/**
* 是否等待并行节点的汇聚
*/
public boolean isWaitParallelRecord(FlowSession session) {
public boolean isWaitRecordMargeParallelNode(FlowSession session) {
FlowRecord currentRecord = session.getCurrentRecord();
if (currentRecord != null && this.getId().equals(currentRecord.getParallelBranchNodeId())) {
RepositoryContext.getInstance().addParallelTriggerCount(currentRecord.getParallelId());
Expand All @@ -180,6 +180,7 @@ public boolean isWaitParallelRecord(FlowSession session) {
if (parallelBranchCount == parallelBranchTotal) {
// 清空并行节点,防止数据继续继承到后续节点
currentRecord.clearParallel();
RepositoryContext.getInstance().clearParallelTriggerCount(currentRecord.getParallelId());
}
return parallelBranchCount != parallelBranchTotal;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public String getType() {

@Override
public List<FlowRecord> generateCurrentRecords(FlowSession session) {
if(this.isWaitParallelRecord(session)){
if(this.isWaitRecordMargeParallelNode(session)){
return List.of();
}
// 构建结束记录
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ public interface ParallelBranchRepository {
int getTriggerCount(String parallelId);

void addTriggerCount(String parallelId);

void clearTriggerCount(String parallelId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ public int getTriggerCount(String parallelId) {
public void addTriggerCount(String parallelId) {
this.cache.put(parallelId, this.getTriggerCount(parallelId) + 1);
}

@Override
public void clearTriggerCount(String parallelId) {
this.cache.remove(parallelId);
}
}