workflow - WorkflowExecutor 接口逻辑说明
2026年1月8日 上午9:50:24
使用预览:
// 1. 创建执行器
WorkflowExecutor workflow = WorkflowExecutor.of(engine, controller, repository);
// 2. 认领任务(检查是否有可操作的待处理任务)
Task current = workflow.claimTask(graph, context);
if (current != null) {
// 3. 提交任务处理
workflow.submitTask(current, TaskAction.FORWARD, context);
}
// 4. 查找后续可能任务(下一步)
Collection<Task> nextTasks = workflow.findNextTasks(graph, context);
1、WorkflowExecutor 接口说明:
| 方法名 | 核心行为 | 副作用 | 开发者视角语义 |
|---|---|---|---|
| claimTask | 权限匹配 + 状态激活 | 写入 WAITING | 认领:从起点开始 eval。若碰撞到 UNKNOWN 节点且 isOperatable 为真,则通过 statePut 将其激活为 WAITING。它是任务从“理论存在”变为“数据库待办”的转折点。 |
| findTask | 逻辑位置探测 | / | 查询:模拟执行流程图。返回当前路径上第一个活跃节点(状态为 WAITING/COMPLETED/TERMINATED)。它不校验权限,只负责告诉调用者“流程逻辑上现在停在哪”。 |
| findNextTasks | 全量路径扫描 | 预测下一步:深度遍历所有可能的分支。忽略权限和当前停顿,扫描所有 UNKNOWN 或 WAITING 的任务点。常用于渲染流程图的“预测轨迹”或处理并行网关(Join/Fork)的探测。 | |
| getState | 仓库快照查询 | / | 查看状态:直接根据 context 和 nodeId 从 StateRepository 中拉取状态枚举。它是最轻量级的检查手段。 |
| submitTask | 状态机驱动 | 写入最新状态 | 流程推进:流转的唯一入口。根据 TaskAction 执行 forwardHandle 或 backHandle。它会触发 postHandleTask 业务钩子,并持久化新状态,从而改变后续 findTask 的探测结果。 |
2、submitTask(TaskAction) 效果说明:
| 动作 (TaskAction) | 中间节点处理 (A, B) | 目标节点 C 的最终状态 | 流程停留在哪里? | 业务语义 |
|---|---|---|---|---|
| FORWARD | / | COMPLETED | C 的下一步 | 正常办理:完成当前节点并流转。 |
| FORWARD_JUMP | 标记为 COMPLETED | WAITING | 停在 C | 跨级指派:跳过中间环节,直接让 C 变为待办。 |
| BACK | / | REMOVED(无状态) | C 的前一步 | 常规退回:撤销当前步,使前驱节点重新激活。 |
| BACK_JUMP | 状态被 REMOVED | WAITING | 停在 C | 指定驳回:撤销中间节点状态,要求 C 重办。 |
| RESTART | 全部 REMOVED | REMOVED | 流程起点 | 全线撤回:清空所有状态,回到 StartNode。 |
| TERMINATE | / | TERMINATE | 停在 C | 终止流程:之后 forwardHandle 会检测到该状态并停止。 |
3、WorkflowExecutor 接口参考
package org.noear.solon.flow.workflow;
import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.FlowEngine;
import org.noear.solon.flow.Graph;
import org.noear.solon.flow.Node;
import org.noear.solon.lang.Nullable;
import org.noear.solon.lang.Preview;
import java.util.Collection;
/**
* 工作流执行器
*
* <p>提供工作流任务的执行框架能力,包括:
* 1. 任务提交执行(前进、后退、跳转等)
* 2. 当前活动任务匹配
* 3. 后续可达任务查找
*
* <p>典型使用场景:
* <pre>{@code
* // 1. 创建执行器
* WorkflowExecutor workflow = WorkflowExecutor.of(engine, controller, repository);
*
* // 2. 匹配当前任务(检查是否有待处理任务)
* Task current = workflow.matchTask(graph, context);
* if (current != null) {
* // 3. 提交任务处理
* workflow.submitTask(current, TaskAction.FORWARD, context);
* }
*
* // 4. 查找后续可能任务
* Collection<Task> nextTasks = workflow.findNextTasks(graph, context);
* }</pre>
*
* <p><b>注意:</b>本执行器专注于流程执行逻辑,不包含实例管理等业务功能。
*
* @since 3.8.1
*/
@Preview("3.4")
public interface WorkflowExecutor {
static WorkflowExecutor of(FlowEngine engine, StateController stateController, StateRepository stateRepository) {
return new WorkflowExecutorDefault(engine, stateController, stateRepository);
}
/**
* 流程引擎
*/
FlowEngine engine();
/**
* 状态控制器
*/
StateController stateController();
/**
* 状态仓库
*/
StateRepository stateRepository();
/// ////////////////////////////////
/**
* 认领当前活动任务(权限匹配,并锁定状态为等待)
*
* @param graphId 图id
* @param context 流上下文(要有人员配置)
*/
@Nullable
default Task claimTask(String graphId, FlowContext context) {
return claimTask(engine().getGraphOrThrow(graphId), context);
}
/**
* 认领当前活动任务(权限匹配,并锁定状态为等待)
*
* @param graph 图
* @param context 流上下文(要有人员配置)
*/
@Nullable
Task claimTask(Graph graph, FlowContext context);
/**
* 寻找当前确定的任务(逻辑探测)
*
* @param graphId 图id
* @param context 流上下文(要有人员配置)
*/
@Nullable
default Task findTask(String graphId, FlowContext context) {
return findTask(engine().getGraphOrThrow(graphId), context);
}
/**
* 寻找当前确定的任务(逻辑探测)
*
* @param graph 图
* @param context 流上下文(要有人员配置)
*/
@Nullable
Task findTask(Graph graph, FlowContext context);
/**
* 寻找下一步可能的任务列表(逻辑探测)
*
* @param graphId 图id
* @param context 流上下文(不需要有人员配置)
*/
default Collection<Task> findNextTasks(String graphId, FlowContext context) {
return findNextTasks(engine().getGraphOrThrow(graphId), context);
}
/**
* 寻找下一步可能的任务列表(寻找所有可能性)
*
* @param graph 图
* @param context 流上下文(逻辑探测)
*/
Collection<Task> findNextTasks(Graph graph, FlowContext context);
/// ////////////////////////////////
/**
* 获取状态
*/
TaskState getState(Node node, FlowContext context);
/// ////////////////////////////////
/**
* 提交任务(如果当前任务为等待介入)
*
* @param task 任务
* @param action 动作
* @param context 流上下文
*/
boolean submitTaskIfWaiting(Task task, TaskAction action, FlowContext context);
/**
* 提交任务
*
* @param task 任务
* @param action 动作
* @param context 流上下文
*/
default void submitTask(Task task, TaskAction action, FlowContext context) {
submitTask(task.getRootGraph(), task.getNode(), action, context);
}
/**
* 提交任务
*
* @param graphId 图id
* @param nodeId 节点id
* @param action 动作
* @param context 流上下文
*/
default void submitTask(String graphId, String nodeId, TaskAction action, FlowContext context) {
submitTask(engine().getGraphOrThrow(graphId), nodeId, action, context);
}
/**
* 提交任务
*
* @param graph 图
* @param nodeId 节点id
* @param action 动作
* @param context 流上下文
*/
default void submitTask(Graph graph, String nodeId, TaskAction action, FlowContext context) {
submitTask(graph, graph.getNodeOrThrow(nodeId), action, context);
}
/**
* 提交任务
*
* @param graph 图
* @param node 节点
* @param action 动作
* @param context 流上下文
*/
void submitTask(Graph graph, Node node, TaskAction action, FlowContext context);
}