­

業務流程可視化-讓你的流程圖”Run”起來(7.運行狀態持久化&輕量工作流支持)

  • 2022 年 8 月 29 日
  • 筆記

前言

感謝大家閱讀本項目系列文章和對項目的支持。
分享一下我對這個項目的新的改進。

之前項目做到了流程設計可視化流程運行結果可視化

本期發佈的版本中實現了中間的運行過程的實時可視化,和流程狀態持久化問題。

大家可以根據項目提供的接口自由擴展自己的工作流實現。
和大家分享一下:

流程狀態實時可視化

首先看效果:

1. 不需要交互的自動化流程

點擊預定按鈕,自動完成預定的流程。

2. 需要交互的嚮導式流程

每點擊一個按鈕,流程向前走一步。

實現方式

工程基於SpringBoot實現,代碼發佈到下面的地址,大家可以自己酌情引用修改:

//github.com/nobuglady/ladybugflow-ui

在ladybugFlow中,有一個接口,FlowUtil.dumpJson()
調用這個接口,可以實時的得到流程的狀態的Json字符串,然後在頁面上用得到Json來生成流程圖即可。

對於【1. 不需要交互的自動化流程】,我們只需要啟動流程後不停的拿到流程狀態的Json即可完成實時可視化的效果。

流程啟動代碼:

@Service
public class Demo1Service {

	@Autowired
	private Demo1Flow demo1Flow;
	
	/**
	 * 啟動流程
	 */
	public void bookingHotel(String username) {
		demo1Flow.startFlow(true, username);
	}
}

對於【2. 需要交互的嚮導式流程】,流程運行到等待節點即進入等待狀態。
這是需要外部運行節點,並將節點運行結果傳給等待的節點,來喚醒該等待節點。

流程啟動&節點狀態更新代碼:


@Service
public class Demo2Service {

	@Autowired
	private Demo2Flow demo2Flow;

	/**
	 * 啟動流程
	 */
	public String start(String username) {
		return demo2Flow.startFlow(false, username);
	}

	/**
	 * 根據流程ID,節點ID和啟動實例ID更新節點狀態(點擊【查詢用戶信息】結束後調用)
	 */
	public void searchUser(String historyId) {
		FlowComponentFactory.getCompleteQueueSender().putCompleteNode(
				"FLOW_2", 
				historyId, 
				"a1a38c2e-0e05-4c68-bd49-f12aea070876", // 節點ID【查詢用戶信息】
				NodeStatusDetail.COMPLETE_SUCCESS, 
				"0");
	}
	
	/**
	 * 根據流程ID,節點ID和啟動實例ID更新節點狀態(點擊【查詢酒店信息】結束後調用)
	 */
	public void searchHotel(String historyId) {
		FlowComponentFactory.getCompleteQueueSender().putCompleteNode(
				"FLOW_2", 
				historyId, 
				"1a90a997-4390-470a-ae7c-626a725438d2",// 節點ID【查詢酒店信息】
				NodeStatusDetail.COMPLETE_SUCCESS, 
				"0");
	}
	
	/**
	 * 根據流程ID,節點ID和啟動實例ID更新節點狀態(點擊【下單】結束後調用)
	 */
	public void order(String historyId) {
		FlowComponentFactory.getCompleteQueueSender().putCompleteNode(
				"FLOW_2", 
				historyId, 
				"52289e99-363d-4453-8077-ca8bdc6d35bf",// 節點ID【下單】
				NodeStatusDetail.COMPLETE_SUCCESS, 
				"0");
	}
	
	/**
	 * 根據流程ID,節點ID和啟動實例ID更新節點狀態(點擊【下單成功】結束後調用)
	 */
	public void success(String historyId) {
		FlowComponentFactory.getCompleteQueueSender().putCompleteNode(
				"FLOW_2", 
				historyId, 
				"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2",// 節點ID【下單成功】
				NodeStatusDetail.COMPLETE_SUCCESS, 
				"0");
	}
}

 

工作流的持久化方式設計

1. 工作流結構的持久化

ladybugflow用Json文件來做工作流結構的持久化。

工作流Json文件包括:流程信息,節點信息和邊信息

ladybugflow提供了圖形界面,可以用拖拽方式來完成工作流的設計和Json文件的生成。

2. 工作流狀態的持久化

對於工作流狀態的保存,我們默認提供了內存中保存的方式。
大家可以根據自己需要,選擇數據庫存儲,文件存儲,Redis,MogoDB存儲等。

系統用三個實體來保存工作流的狀態:

・流程歷史實體
・節點歷史實體
・邊歷史實體

和一個接口來描述對上述實體的操作:

io.github.nobuglady.network.fw.component.IFlowAccessor

大家只要實現上面的接口中的方法,即可以完成對工作流狀態的保存。

比如存到數據庫中,或者存到Redis中等。

對於自定義的持久化類,需要再ladybug.properties中做如下配置

flow.accessor = 你的持久化類全路徑

下面我們以mysql為例,介紹數據操作接口的實現方式。

 

流程狀態持久化實現(MySql)

接下來我們介紹mysql作為持久化的實現方式。

首先,需要做成實體對應的相關表,如下。

・流程歷史表
・節點歷史表
・邊歷史表

對應的SQL文件參考這裡

//github.com/nobuglady/ladybugflow-ui/blob/main/db/script.sql

然後,我們用sql的方式實現每個接口的方法。

我們針對每個表做一個Dao,實現針對錶的操作

具體實現請參考這裡:

//github.com/nobuglady/ladybugflow-ui/tree/main/src/main/java/io/github/nobuglady/network/ui/dao

 

最後我們將Dao集成到SpringBoot中,即完成了流程狀態的持久化。

	private HistoryFlowDao historyFlowDao;
	private HistoryNodeDao historyNodeDao;
	private HistoryEdgeDao historyEdgeDao;

	public FlowAccessor() {
		historyFlowDao = SpringContextBridge.getInstance().getHistoryFlowDao();
		historyNodeDao = SpringContextBridge.getInstance().getHistoryNodeDao();
		historyEdgeDao = SpringContextBridge.getInstance().getHistoryEdgeDao();
	}

運行效果如下,可以看到系統已經通過發SQL的方式進行持久化查詢與更新。

[I]2022/08/25 17:17:46.015 [your flow id][5bc43da8-7b11-4746-b886-31fd1c1bf754] pool-1-thread-2:execute node id:16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2
[I]2022/08/25 17:17:46.015 [your flow id][5bc43da8-7b11-4746-b886-31fd1c1bf754] pool-1-thread-2:execute node name:下單成功
下單成功開始 (模擬業務等待3秒)
下單成功結束
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: SELECT * FROM history_node WHERE flow_id = ? and node_id = ? and history_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: your flow id(String), 16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==      Total: 1
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: update history_node set node_status = ?, node_status_detail = ?, update_user = ?, update_time = now() where flow_id = ? and history_id = ? and node_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: 22(Integer), 1(Integer), testUser(String), your flow id(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String), 16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==    Updates: 1
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: update history_node set node_status = ?, update_user = ?, update_time = now() where flow_id = ? and history_id = ? and node_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: 100(Integer), testUser(String), your flow id(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String), 16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==    Updates: 1
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: SELECT * FROM history_edge WHERE flow_id = ? and history_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: your flow id(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==      Total: 6
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: SELECT * FROM history_node WHERE flow_id = ? and history_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: your flow id(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==      Total: 5
2022/08/25 17:17:49 DEBUG [Thread-4] - ==>  Preparing: SELECT * FROM history_flow WHERE flow_id = ? and history_id = ?
2022/08/25 17:17:49 DEBUG [Thread-4] - ==> Parameters: your flow id(String), 5bc43da8-7b11-4746-b886-31fd1c1bf754(String)
2022/08/25 17:17:49 DEBUG [Thread-4] - <==      Total: 1

大家可以根據自己的需要自由的擴展持久化的方式。

 

小型工作流的使用

對於工作流在業務系統中的使用,我們建議增加一個Flow層來處理工作流,如下:

Service層調用Flow層來實現工作流的啟動,如下所示:

@Service
public class Demo1Service {

	@Autowired
	private Demo1Flow demo1Flow;

	public void bookingHotel(String username) {
		// 啟動流程
		demo1Flow.startFlow(true, username);
	}
}

工作流的設計

首先需要在我們提供的工具中設計工作流。

然後點擊【update json】按鈕生成json文件。

然後將生成的Json文件放入Flow層中,並且建立一個同名的Java文件集成自FlowRunner,來提供工作流的啟動。

工作流的監控

ladybugflow提供了一個監控工作流的例子,大家可以根據需要自己擴展。

瀏覽器打開 //localhost:8080/list

可以顯示所有的工作流,點擊【detail】鏈接,即可查看工作流的詳細狀態。

點擊【clear complete】按鈕,即可刪除所有已經完成的工作流,
點擊【clear error】按鈕,即可刪除所有的運行錯誤的工作流。

 

後續會加入權限控制等功能,歡迎大家持續關注本項目。

感謝您閱讀到這裡

最後

源碼:

//github.com/nobuglady/ladybugflow

//github.com/nobuglady/ladybugflow-ui