go语言,yaml实现简单的workflow工作流
目录
1.创建一个yaml文件,名字可以是student.yaml
2.创建go文件测试
3.执行结果
本文章内容,只是一个简单的案例,但足够映射到一个大的项目中。
工作流作用:工作流的作用就是通过yaml配置文件,将关于本工作流的一个个task任务串联起来形成一个大的功能体。通过加载yaml,将任务执行的顺序固定化。
说白了就是对任务进行编排,当大流量来的时候,可以让线程排队执行。
比如:用户注册,需要验证哪些参数,比如验证邮件地址,验证手机号,可以把这些小功能放到一个小任务中,也就是task。然后将这些任务串起来,形成一个大功能,也就是工作流。
现在举个具体的案例,来实现一个简易的工作流,更加通俗易懂。
这里举了一个用户注册的功能。
1.创建一个yaml文件,名字可以是student.yaml
yaml都是key:value结构。- 代表的是一个数组,数组中的元素是key:value结构,这个value还可以是数组类型等等。
# 工作流名字
workflow: "user"
# 具体执行的任务
tasks:
# 邮件地址的有效性
# 单斜杠后面 - 后面是一个列表
# name:task的名字
# action:具体task对应的方法
# params:相关参数,这个参数可能是前端传来的,需要取出,也可能是上一个task的结果。
# requires:这个任务是否有依赖,也就是这个任务执行的时候需要执行的另一个任务。
- name: "validate_email"
action: "validate_email_action"
params:
email: "user@example.com"
requires: []
- name: "create_user"
action: "create_user_action"
params:
"username": "yaml"
"password": "123456"
# 这儿创建用户的时候需要验证邮件地址是否有效
requires:
- "validate_email"
- name: "send_welcome_email"
action: "send_welcome_email_action"
params:
"recipient": "user@example.com"
"subject": "Welcome to our platform!"
"body":
"Dear John Doe,
Welcome to our platform! We are excited to have you on board.
Best regards,
The Team"
# 发送这个welcome消息的时候,代表创建成功。
"requires":
- "create_user"
2.创建go文件测试
创建一个main.go
package main
import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
)
// Workflow 结构体
type Workflow struct {
Name string `yaml:"workflow"`
Tasks []Task `yaml:"tasks"`
}
// Task 结构体
type Task struct {
Name string `yaml:"name"`
Action string `yaml:"action"`
Params map[string]any `yaml:"params"`
Requires []string `yaml:"requires"`
}
func main() {
data, err := ioutil.ReadFile("workflow/student.yml")
if err != nil {
fmt.Println("读取配置文件失败:", err)
return
}
var workflow Workflow
// yaml反序列化,将字节类型的数据反序列化到结构体中
err = yaml.Unmarshal(data, &workflow)
if err != nil {
fmt.Println("data反序列化错误:", err)
return
}
// 执行工作流的任务
// 获取工作流
for _, task := range workflow.Tasks {
if checkDependecies(task.Requires) {
fmt.Println("执行任务", task.Name)
result, err := executeTask(task.Action, task.Params)
if err != nil {
fmt.Println("任务执行失败!", err)
return
}
fmt.Println("执行的结果为:", result)
fmt.Println("---")
} else {
fmt.Println("跳过任务:", task.Name)
}
fmt.Println("task.Params:", task.Params)
fmt.Println("task.Action:", task.Action)
fmt.Println("task.Requires:", task.Requires)
fmt.Println("task.Name:", task.Name)
if task.Params["username"] != "" {
fmt.Println("task.Params username:", task.Params["username"])
}
}
fmt.Println("用户执行成功!~")
}
// 检查任务的依赖是否满足
func checkDependecies(requires []string) bool {
// todo 验证参数
return true
}
// 执行任务
func executeTask(action string, params map[string]any) (string, error) {
switch action {
case "validate_email_action":
// todo 验证邮件地址的有效性
return "ok", nil
case "create_user_action":
//todo 创建用户
return "user_id", nil
case "send_welcome_email_action":
// 发送消息
return "ok", nil
default:
return "", fmt.Errorf("未知的任务:%s", action)
}
}
3.执行结果
我把参数信息都打印出来了
执行任务 validate_email
执行的结果为: ok
---
task.Params: map[email:user@example.com]
task.Action: validate_email_action
task.Requires: []
task.Name: validate_email
task.Params username: <nil>
执行任务 create_user
执行的结果为: user_id
---
task.Params: map[password:123456 username:yaml]
task.Action: create_user_action
task.Requires: [validate_email]
task.Name: create_user
task.Params username: yaml
执行任务 send_welcome_email
执行的结果为: ok
---
task.Params: map[body:Dear John Doe, Welcome to our platform! We are excited to
have you on board. Best regards, The Team recipient:user@example.com subject:Wel
come to our platform!]
task.Action: send_welcome_email_action
task.Requires: [create_user]
task.Name: send_welcome_email
task.Params username: <nil>
用户执行成功!~