Solon v3.8.0

workflow - WorkflowExecutor 接口逻辑说明

</> markdown
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/COMPLETEDC 的下一步正常办理:完成当前节点并流转。
FORWARD_JUMP标记为 COMPLETEDWAITING停在 C跨级指派:跳过中间环节,直接让 C 变为待办。
BACK/REMOVED(无状态)C 的前一步常规退回:撤销当前步,使前驱节点重新激活。
BACK_JUMP状态被 REMOVEDWAITING停在 C指定驳回:撤销中间节点状态,要求 C 重办。
RESTART全部 REMOVEDREMOVED流程起点全线撤回:清空所有状态,回到 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);
}