業務視覺化-讓你的流程圖"Run"起來(6.定時任務&Spring-Batch的整合)

2022-08-11 09:00:11

前言

首先,感謝大家對上一篇文章[業務視覺化-讓你的流程圖"Run"起來(5.SpringBoot整合&微服務編排)]的支援。

分享一下近期我對這個專案的一些改進。

在專案中,經常會有一些批次處理的定時任務需要設定,目前的java專案一般採用Spring-Batch來作為批次處理的平臺。

但是Spring-Batch在對Job流程(並行,分支,條件分支,合併等)的支援略顯複雜臃腫。

尤其是流程視覺化這方面幾乎不支援。

所以,最近對ladybugflow做了改進,在天然支援視覺化流程的基礎上,追加了對定時任務的支援。

本篇文章介紹ladybugflow定時任務的設定,和與SpringBatch相結合完成批次處理的視覺化操作的例子。

定時任務

對於流程的執行,前面文章介紹了流程的啟動方法,如下:

Flow1 testFlow = new Flow1();
testFlow.startFlow(true);

這樣只能完成流程的一次啟動,如果需要定時啟動流程,ladybugflow提供了在啟動節點中設定cron表示式的方法來實現定時啟動流程。

cron表示式

我們首先簡單的瞭解一下cron表示式

Cron表示式是有六個空格分隔的時間和日期欄位(域)組成的字串。

 ┌───────────── second (0-59)
 │ ┌───────────── minute (0 - 59)
 │ │ ┌───────────── hour (0 - 23)
 │ │ │ ┌───────────── day of the month (1 - 31)
 │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC)
 │ │ │ │ │ ┌───────────── day of the week (0 - 7)
 │ │ │ │ │ │          (0 or 7 is Sunday, or MON-SUN)
 │ │ │ │ │ │
 *  *  *  *  *  *

比如:

「0 0 * * * *」 = 每天 00:00。
"*/10 * * * * *" = 每 10 秒。
「0 0 8-10 * * *」 = 每天 8、9 和 10 個小時。
"0 0 6,19 * * *" = 每天早上 6:00 和晚上 7:00。
「0 0/30 8-10 * * *」 = 每天 8:00、8:30、9:00、9:30、10:00 和 10:30。
"0 0 9-17 * * MON-FRI" = 工作日 9 到 5
「0 0 0 25 12 ?」 = 聖誕節午夜
"0 0 0 L * *" = 每個月的午夜
"0 0 0 L-3 * *" = 每月第三天到最後一天午夜
"0 0 0 1W * *" = 每月第一個工作日午夜
"0 0 0 LW * *" = 每月最後一個工作日的午夜
"0 0 0 * * 5L" = 每月最後一個星期五的午夜
"0 0 0 * * THUL" = 每月最後一個星期四的午夜
"0 0 0 ? * 5#2" = 每月第二個星期五的午夜
"0 0 0 ? * MON#1" = 每月第一個星期一的午夜

在ladybugflow中設定cron表示式

在流程編輯器中,將流程的首節點的啟動型別設定成Timer,然後輸入cron表示式,如下圖所示

點選更新,更新json,

將json字串拷貝到工程裡,

啟動工程,如下:

執行結果

[I]2022/08/09 18:23:35.547  main:ladybugflow.properties in root path not found, use default configuration
[I]2022/08/09 18:23:35.558  main:NodePool started.
[I]2022/08/09 18:23:35.559  main:Ready queue consumer thread started.
[I]2022/08/09 18:23:35.610  main:Complete queue consumer thread started.
[I]2022/08/09 18:23:36.230 [your flow id][283eb8de-e12c-4de0-9484-51da87538032] main:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查詢使用者資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查詢酒店資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下單","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下單成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[your flow id] next execute time:2022/08/09 18:24:00
[I]2022/08/09 18:24:00.027 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] ThreadPoolTaskScheduler-1:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查詢使用者資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查詢酒店資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下單","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下單成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[I]2022/08/09 18:24:00.032 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node id:1
[I]2022/08/09 18:24:00.032 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node name:start
啟動開始 (模擬業務等待3秒)
啟動結束
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node id:a1a38c2e-0e05-4c68-bd49-f12aea070876
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node name:查詢使用者資訊
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:1a90a997-4390-470a-ae7c-626a725438d2
查詢使用者資訊開始 (模擬業務等待3秒)
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:查詢酒店資訊
查詢酒店資訊開始 (模擬業務等待3秒)
查詢使用者資訊結束
查詢酒店資訊結束
[I]2022/08/09 18:24:06.071 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:52289e99-363d-4453-8077-ca8bdc6d35bf
[I]2022/08/09 18:24:06.071 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:下單
下單開始 (模擬業務等待3秒)
下單結束
[I]2022/08/09 18:24:09.074 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2
[I]2022/08/09 18:24:09.074 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:下單成功
下單成功開始 (模擬業務等待3秒)
下單成功結束
[I]2022/08/09 18:24:12.083 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] Thread-1:Complete success.
[I]2022/08/09 18:24:12.087 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] Thread-1:json:
{"nodes":[{"id": "1","label": "start" ,"color": "#36AE7C"},{"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876","label": "查詢使用者資訊" ,"color": "#36AE7C"},{"id": "1a90a997-4390-470a-ae7c-626a725438d2","label": "查詢酒店資訊" ,"color": "#36AE7C"},{"id": "52289e99-363d-4453-8077-ca8bdc6d35bf","label": "下單" ,"color": "#36AE7C"},{"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label": "下單成功" ,"color": "#36AE7C"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from": "1","to": "a1a38c2e-0e05-4c68-bd49-f12aea070876","arrows": "to"},{"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7","from": "1","to": "1a90a997-4390-470a-ae7c-626a725438d2","arrows": "to"},{"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c","from": "1a90a997-4390-470a-ae7c-626a725438d2","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"},{"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from": "52289e99-363d-4453-8077-ca8bdc6d35bf","to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","arrows": "to"},{"id": "19f2f329-8163-4dc6-a353-800df79d18a6","from": "a1a38c2e-0e05-4c68-bd49-f12aea070876","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"}]}

 

定時任務的實現方式

ladybugflow採用spring的scheduling來實現對cron表示式的解析,

流程啟動後,如果首節點型別是Timer,則會根據cron表示式來向ThreadPoolTaskScheduler中註冊一個定時任務。

taskScheduler.schedule(new Runnable() {
	@Override
	public void run() {

		try {
			FlowRunner flowRunnerNew = flowRunner.getClass().newInstance();

			String flowPath = flowRunnerNew.getClass().getName();

			if (StringUtil.isNotEmpty(jsonFileName)) {
				flowPath = jsonFileName.replace(".json", "");
			}

			FlowEntity flow = createHistory(flowPath);
			String flowId = flow.flowEntity.getFlowId();
			String historyId = flow.flowEntity.getHistoryId();

			FlowContainer.flowRunnerMap.put(flowId + "," + historyId, flowRunnerNew);
			
			HistoryNodeEntity firstNode = FlowContainer.selectNodeByKey(flowId, nodeId, historyId);
			firstNode.setNodeStatus(NodeStatus.READY);
			startNode(flowId, historyId, nodeId);

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

	}
}, new CronTrigger(cron));

 

Spring-Batch與ladybugflow的整合

1.新建一個Spring-Batch工程,並且匯入ladybugflow。

build.gradle

plugins {
	id 'org.springframework.boot' version '2.7.2'
	id 'io.spring.dependency-management' version '1.0.12.RELEASE'
	id 'java'
}

group = 'nobuglady'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-batch'
	implementation 'io.github.nobuglady:ladybugflow:0.0.8'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

將生成的Json檔案和對應的Flow.java檔案放在同一個目錄下:

Flow1.java

package io.github.nobuglady.network.demo.batch.ladybugflow;

import org.springframework.stereotype.Component;

import io.github.nobuglady.network.fw.FlowRunner;
import io.github.nobuglady.network.fw.annotation.Node;

/**
 * 
 * @author NoBugLady
 *
 */
@Component
public class Flow1 extends FlowRunner {

	private String result;
	
	public String getResult() {
		return result;
	}
	
	@Node(label = "start")
	public void processStart() throws InterruptedException {
		System.out.println("啟動開始 (模擬業務等待3秒)");
		Thread.sleep(3000);
		System.out.println("啟動結束");
	}

	@Node(label = "查詢使用者資訊")
	public void processSearchUser() throws InterruptedException {
		System.out.println("查詢使用者資訊開始 (模擬業務等待3秒)");
		Thread.sleep(3000);
		System.out.println("查詢使用者資訊結束");
	}

	@Node(label = "查詢酒店資訊")
	public void processSearchHotel() throws InterruptedException {
		System.out.println("查詢酒店資訊開始 (模擬業務等待3秒)");
		Thread.sleep(3000);
		System.out.println("查詢酒店資訊結束");
	}

	@Node(label = "下單")
	public void processOrder() throws InterruptedException {
		System.out.println("下單開始 (模擬業務等待3秒)");
		Thread.sleep(3000);
		System.out.println("下單結束");
	}

	@Node(label = "下單成功")
	public void processSuccess() throws InterruptedException {
		System.out.println("下單成功開始 (模擬業務等待3秒)");
		Thread.sleep(3000);
		System.out.println("下單成功結束");
		result = "success";
	}
}

Flow1.json

{
	"flowId": "your flow id",
	"nodes": [
		{
			"id": "1",
			"label": "start",
			"readyCheck": 0,
			"startType": 3,
			"startCron": "0 0/1 * * * ?"
		},
		{
			"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
			"label": "查詢使用者資訊",
			"readyCheck": 0
		},
		{
			"id": "1a90a997-4390-470a-ae7c-626a725438d2",
			"label": "查詢酒店資訊",
			"readyCheck": 0
		},
		{
			"id": "52289e99-363d-4453-8077-ca8bdc6d35bf",
			"label": "下單",
			"readyCheck": 0
		},
		{
			"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2",
			"label": "下單成功",
			"readyCheck": 0
		}
	],
	"edges": [
		{
			"id": "1",
			"from": "1",
			"to": "2",
			"arrows": "to"
		},
		{
			"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4",
			"from": "1",
			"to": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
			"arrows": "to"
		},
		{
			"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7",
			"from": "1",
			"to": "1a90a997-4390-470a-ae7c-626a725438d2",
			"arrows": "to"
		},
		{
			"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c",
			"from": "1a90a997-4390-470a-ae7c-626a725438d2",
			"to": "52289e99-363d-4453-8077-ca8bdc6d35bf",
			"arrows": "to"
		},
		{
			"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37",
			"from": "52289e99-363d-4453-8077-ca8bdc6d35bf",
			"to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2",
			"arrows": "to"
		},
		{
			"id": "19f2f329-8163-4dc6-a353-800df79d18a6",
			"from": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
			"to": "52289e99-363d-4453-8077-ca8bdc6d35bf",
			"arrows": "to"
		}
	]
}

在啟動的類中啟動流程

LadybugflowDemoBatchApplication.java

package io.github.nobuglady.network.demo.batch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

import io.github.nobuglady.network.demo.batch.ladybugflow.Flow1;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class LadybugflowDemoBatchApplication implements ApplicationRunner {

	@Autowired
	private Flow1 flow1;
	
	public static void main(String[] args) {
		SpringApplication.run(LadybugflowDemoBatchApplication.class, args);
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {

		flow1.startFlow(true);
		System.out.println(flow1.getResult());
		
	}

}

執行結果:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.2)

2022-08-09 18:21:04.166  INFO 3208 --- [           main] .n.n.d.b.LadybugflowDemoBatchApplication : No active profile set, falling back to 1 default profile: "default"
2022-08-09 18:21:04.769  INFO 3208 --- [           main] .n.n.d.b.LadybugflowDemoBatchApplication : Started LadybugflowDemoBatchApplication in 0.907 seconds (JVM running for 1.78)
[I]2022/08/09 18:21:04.772  main:ladybugflow.properties in root path not found, use default configuration
[I]2022/08/09 18:21:04.773  main:NodePool started.
[I]2022/08/09 18:21:04.774  main:Ready queue consumer thread started.
[I]2022/08/09 18:21:04.779  main:Complete queue consumer thread started.
[I]2022/08/09 18:21:04.961 [your flow id][a31bb47d-be78-491d-9ecd-7d59302b565a] main:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查詢使用者資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查詢酒店資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下單","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下單成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[your flow id] next execute time:2022/08/09 18:22:00
[I]2022/08/09 18:22:00.020 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] ThreadPoolTaskScheduler-1:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查詢使用者資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查詢酒店資訊","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下單","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下單成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[I]2022/08/09 18:22:00.023 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:1
[I]2022/08/09 18:22:00.024 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:start
啟動開始 (模擬業務等待3秒)
啟動結束
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:a1a38c2e-0e05-4c68-bd49-f12aea070876
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:查詢使用者資訊
查詢使用者資訊開始 (模擬業務等待3秒)
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-2:execute node id:1a90a997-4390-470a-ae7c-626a725438d2
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-2:execute node name:查詢酒店資訊
查詢酒店資訊開始 (模擬業務等待3秒)
查詢酒店資訊結束
查詢使用者資訊結束
[I]2022/08/09 18:22:06.034 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:52289e99-363d-4453-8077-ca8bdc6d35bf
[I]2022/08/09 18:22:06.034 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:下單
下單開始 (模擬業務等待3秒)
下單結束
[I]2022/08/09 18:22:09.043 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2
[I]2022/08/09 18:22:09.044 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:下單成功
下單成功開始 (模擬業務等待3秒)
下單成功結束
[I]2022/08/09 18:22:12.053 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] Thread-4:Complete success.
[I]2022/08/09 18:22:12.055 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] Thread-4:json:
{"nodes":[{"id": "1","label": "start" ,"color": "#36AE7C"},{"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876","label": "查詢使用者資訊" ,"color": "#36AE7C"},{"id": "1a90a997-4390-470a-ae7c-626a725438d2","label": "查詢酒店資訊" ,"color": "#36AE7C"},{"id": "52289e99-363d-4453-8077-ca8bdc6d35bf","label": "下單" ,"color": "#36AE7C"},{"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label": "下單成功" ,"color": "#36AE7C"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from": "1","to": "a1a38c2e-0e05-4c68-bd49-f12aea070876","arrows": "to"},{"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7","from": "1","to": "1a90a997-4390-470a-ae7c-626a725438d2","arrows": "to"},{"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c","from": "1a90a997-4390-470a-ae7c-626a725438d2","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"},{"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from": "52289e99-363d-4453-8077-ca8bdc6d35bf","to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","arrows": "to"},{"id": "19f2f329-8163-4dc6-a353-800df79d18a6","from": "a1a38c2e-0e05-4c68-bd49-f12aea070876","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"}]}

感謝您閱讀到這裡。

最後

原始碼:https://github.com/nobuglady/ladybugflow

本章範例原始碼:https://github.com/nobuglady/ladybugflow-demo/tree/main/ladybugflow-demo-batch