zoukankan      html  css  js  c++  java
  • 关于工作流:flowable中终止流程二

    终止流程代码
    
    public void stopProcessInstanceById(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
     if (processInstance != null) {
            //1、获取终止节点
     List<EndEvent> endNodes =findEndFlowElement(processInstance.getProcessDefinitionId());
     String endId = endNodes.get(0).getId();
     //2、执行终止
     List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
     List<String> executionIds = new ArrayList<>();
     executions.forEach(execution -> executionIds.add(execution.getId()));
     runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
     log.info("终止processInstanceId:{}胜利",processInstanceId);
     }else {
           log.info("不存在运行的流程实例processInstanceId:{},请确认!",processInstanceId);
     }
    }
    public List findEndFlowElement(String processDefId) {
        Process mainProcess = repositoryService.getBpmnModel(processDefId).getMainProcess();
     Collection<FlowElement> list = mainProcess.getFlowElements();
     if (CollectionUtils.isEmpty(list)) {
            return Collections.EMPTY_LIST;
     }
        return list.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList());
    }
    
    
    runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId)
    并没有changeState,正确的应用姿态是
    
    runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
    没有调用changeState办法是不会失效的
    坑2:在serviceTask中调用
    
    flowableInstanceService.stopProcessInstanceById(delegateExecution.getProcessInstanceId());
    若该serviceTask中抛出Exception,会产生诡异的操作:
    流程并没有顺利终止掉。
    为什么?flowable中应用的默认的流传行为为Required(没有事务则新建一个事务),而serviceTask是在事务中执行的(能够理解flowable源码之命令模式,若servicetask中抛出异样,则相应的数据库操作会被全副回滚掉),完结流程这个办法会沿用这个事务,当该servicetask抛出谬误后,会回滚掉筹备提交的sqlsession
    解决思路:
    1.应用多线程,异步执行终止流程操作
    
    executorService.submit(() -> flowableInstanceService.stopProcessInstanceById(delegateExecution.getProcessInstanceId()));
    引发问题:史诗级巨坑,排查了很久,偶然执行胜利,偶然执行失败,不抛错,也没有异样。
    排查问题思路:flowableInstanceService.stopProcessInstanceById真的执行结束了吗?为什么数据库的状态没有扭转,这里是其余线程,没有再开启事务了,不存在之前的事务流传行为的问题。
    通过打印日志的形式,我哭了
    
    executorService.execute(() -> {
        log.info("终止processInstanceId:{}工作开始",delegateExecution.getProcessInstanceId());
     flowableInstanceService.stopProcessInstanceById(delegateExecution.getProcessInstanceId());
     log.info("终止processInstanceId:{}工作完结",delegateExecution.getProcessInstanceId());
    });
    工作完结的日志居然没有打印,我狐疑可能抛出了异样,为了验证问题所在,线程减少日志打印解决
    
    @Bean
    public ExecutorService executorService() {
        return Executors.newSingleThreadExecutor(new HandleThreadFactory());
    }
    class HandleThreadFactory implements ThreadFactory {
        @Override
     public Thread newThread(Runnable r) {
            System.out.println("create thread t");
     Thread t = new Thread(r);
     System.out.println("set uncaughtException for t");
     t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
     public void uncaughtException(Thread t, Throwable e) {
                    log.error("caught exception:" + e);
     }
            });
     return t;
     }
    }
    无果??异样没有被捕捉到,原来,应用executorService.execute()才会被捕捉到,于是更换成executorService.execute()办法来运行
    
    原来,这个中央抛出了异样。思考了很久,应该是并发导致的问题
    serviceTask的线程为A线程,完结流程的线程为B线程
    A线程当前任务节点为servicetask1,
    B线程读取当前任务节点为servicetask1,并希图挪动到end节点
    A线程抛错或者serviceTask1执行结束,工作节点多会变动为定时器(重试机制)或者serviceTask2(失常流转)
    B线程执行操作,挪动到end节点,伪代码sql为update to end where node is serviceTask1,然而留神留神,A线程曾经commit了具体的最新的以后节点的值,A线程拿到的还是老数据,故操作失败,updateCount为0,抛出异
    
    
    拓展:flowable为了并发性能,应用的是伪并发,即乐观锁机制,乐观的认为所有的数据都是没有竞争的,不减轻锁。失败就会抛出此异样
    最终解决办法:
    不抛异样,间接同步终止流程
    
     
    
    flowableInstanceService.stopProcessInstanceById(delegateExecution.getProcessInstanceId());
    

      转载   https://lequ7.com/guan-yu-gong-zuo-liu-flowable-zhong-zhong-zhi-liu-cheng-er.html

  • 相关阅读:
    YARN分析系列之三 -- 从脚本入口分析 ResourceManager的初始化过程
    YARN分析系列之二 -- Hadoop YARN各个自模块说明
    MacOS平台上编译 hadoop 3.1.2 源码
    YARN分析系列之一 -- 总览YARN组件
    WCF入门 (14)
    WCF入门 (13)
    WCF入门(12)
    WCF入门(11)
    WCF入门(10)
    WCF入门(9)
  • 原文地址:https://www.cnblogs.com/xianz666/p/14680695.html
Copyright © 2011-2022 走看看