Solon v3.8.3

workflow - 工作流服务相关接口

</> markdown
2026年1月13日 下午7:23:59

WorkflowExecutor 是在 Solon Flow 的基础上,通过驱动定制和封装实现的轻量级工作流执行器

状态服务相关的主要接口包括:

主要接口描述
WorkflowExecutor工作流执行器
Task工作任务
TaskAction任务动作
TaskState任务状态
StateController状态控制器接口。提供状态控制(是否可操作,是否自动前进)
StateRepository状态仓库接口。提供状态保存与获取

StateController 框架内提供有(也可按需定制):

实现描述
BlockStateController阻塞状态控制器(所有节点有权操作,类似超级管理员)
NotBlockStateController不阻塞状态控制器(像无状态一样执行,除非中断,中断处可恢复执行)。v3.5.0 后支持
ActorStateController参与者状态控制器(节点元数据匹配参与者后有权操作,没有配置的会自动前进)

StateRepository 框架内提供有(也可按需定制):

实现描述
InMemoryStateRepository内存状态仓库(基于 Map 封装)
RedisStateRepositoryRedis 状态仓库(基于 Redis 封装)

2、Task 属性

操作描述
run(context)运行当前节点任务(如果有可执行代码?)
getRootGraph():Graph获取根图(跨多图执行时,会有根图概念)
getNode():Node获取当前节点(进则获取节点的元数据)
getNodeId():String获取当前节点Id(v3.8.0 后支持)
getState():StateType获取当前节点“状态类型”(等待、完成、等...)

获取示例:

//查询任务:查找下一个待处理节点,或者完结的节点
Task task = workflow.findTask("c1", FlowContext.of("i-1"));

//认领任务:权限匹配 + 状态激活(自动前进的会跳过)
//Task task = workflow.claimTask("c1", FlowContext.of("i-1"));

3、WorkflowExecutor 构建

@Configuration
public class DemoCom {
    @Bean
    public WorkflowExecutor workflowOf(FlowEngine flowEngine) {
        return WorkflowExecutor.of(engine,
                new ActorStateController(), 
                new InMemoryStateRepository()); 

    }
}

WorkflowExecutor 一组偏“审批”场景的接口(中间需要参与者介入。一般配合 ActorStateController):

接口描述
claimTask(...)->Task认领任务:权限匹配 + 状态激活(自动前进的会跳过)
findTask(...)->Task查询任务:查找下一个待处理节点,或者完结的节点
findNextTasks(...)->Collection<Task>查询下一步任务列表
submitTask(...)提交任务(会产生“前进”或“后退”的效果)
submitTaskIfWaiting(...)提交任务(会检测是否在等待参与者操作)
getState(...)获取流程节点状态

4、 WorkflowExecutor 接口参考

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);
}