• Activiti系列:是否可以让某些流程的信息写到历史表,而另外一些不写?


    一、起因
        打算使用activiti的定时启动事件来定时启动流程,然后再在该流程中针对每个用户启动另外一个流程实例来计算每个用户的实时账单,系统的用户数一般是1000~2000(此处假设是2000),实时账单一般每小时计算一次,那么一天的数据量就是 2000x24=48000,一个月就是150w,一年就是1800w,这样的记录数对于activiti的历史表来说就有点多了,很怀疑他在这样的数据量下是否还可以跑得比较顺畅。我想activiti设计的初衷不是用来做这种大规模的自动触发的、没有人工参与的流程的。
        所以就考虑是不是通过某些设置,可以让这种自动执行的流程不用写历史表,但是其他的需要人工参与的流程还是要能够正常记录历史记录。
        

    二、源码阅读    
        然后就阅读了activiti 5.18的源码,分析如下:
        写历史表示在DefaultHistoryManager,中实现的,通过HistoryLevel来控制,相关的代码如下:
    1. public void recordProcessInstanceStart(ExecutionEntity processInstance) {
    2. if(isHistoryLevelAtLeast(HistoryLevel.ACTIVITY)) {
    3. HistoricProcessInstanceEntity historicProcessInstance = new HistoricProcessInstanceEntity(processInstance);
    4. // Insert historic process-instance
    5. getDbSqlSession().insert(historicProcessInstance);
    6. ....
    7. }

    而isHistoryLevelAtLeast的实现如下:
    1. public boolean isHistoryLevelAtLeast(HistoryLevel level) {
    2. if(log.isDebugEnabled()) {
    3. log.debug("Current history level: {}, level required: {}", historyLevel, level);
    4. }
    5. // Comparing enums actually compares the location of values declared in the enum
    6. return historyLevel.isAtLeast(level);
    7. }


    HistoryLevel枚举类型的是实现如下
    1. /**
    2. * Enum that contains all possible history-levels.
    3. *
    4. * @author Frederik Heremans
    5. */
    6. public enum HistoryLevel {
    7. NONE("none"),
    8. ACTIVITY("activity"),
    9. AUDIT("audit"),
    10. FULL("full");
    11. private String key;
    12. private HistoryLevel(String key) {
    13. this.key = key;
    14. }
    15. /**
    16. * @param key string representation of level
    17. * @return {@link HistoryLevel} for the given key
    18. * @throws ActivitiException when passed in key doesn't correspond to existing level
    19. */
    20. public static HistoryLevel getHistoryLevelForKey(String key) {
    21. for(HistoryLevel level : values()) {
    22. if(level.key.equals(key)) {
    23. return level;
    24. }
    25. }
    26. throw new ActivitiIllegalArgumentException("Illegal value for history-level: " + key);
    27. }
    28. /**
    29. * String representation of this history-level.
    30. */
    31. public String getKey() {
    32. return key;
    33. }
    34. /**
    35. * Checks if the given level is the same as, or higher in order than the
    36. * level this method is executed on.
    37. */
    38. public boolean isAtLeast(HistoryLevel level) {
    39. // Comparing enums actually compares the location of values declared in the enum
    40. return this.compareTo(level) >= 0;
    41. }
    42. }

    可以看出,是否要在历史记录表中记录流程执行信息,是由 DefaultHistoryManager的level成员来决定的,只有在ACTIVITY及其以上级别才会记录。
    DefaultHistoryManager是全局的,和某个具体的流程或者流程实例是没有关系的,所以在默认实现中,activiti不支持设置单个流程或者流程实例是否写历史记录表。
     
    三、解决方案
    如果我们真的想要实现针对每个流程或者流程实例都可以控制他是否写日志,要有两点修改:
    1.要给ExecutionEntity添加一个HistoryLevel属性,或者流程变量,可能用流程变量更方便一些,就不需要对原有的类做改动了;
    2.要实现一个自定义的HistoryManager,然后注入到CommandContext中。在这个自定义的HistoryManager中需要能够判断ExecutionEntity的HistoryLevel的等级,以决定是否需要记录他的历史信息;




  • 相关阅读:
    python 线性回归(Linear Regression)预测波士顿房价
    python支持向量机分类MNIST数据集
    python朴素贝叶斯分类MNIST数据集
    感知机(perceptron)
    LMS Algorithm 最小均方算法
    线性回归(Linear Regression)和最小二乘法(ordinary least squares)
    KNN实现mnist、fashion mnist数据集的分类
    JavaScript一些常见的知识点
    用js做一个许愿墙
    js做留言板(可以评论 删除评论 评论时间)
  • 原文地址:https://www.cnblogs.com/strinkbug/p/4977012.html
Copyright © 2020-2023  润新知