dashboard/pkg/fsm/fsm.go
2025-05-21 16:46:17 +08:00

89 lines
2.6 KiB
Go

package fsm
import (
"context"
"fmt"
"github.com/looplab/fsm"
)
// Task 任务结构体
type Task struct {
ID string
FSM *fsm.FSM
UserID string // 示例:记录操作者
}
// NewTask 创建新任务
func NewTask(id string) *Task {
task := &Task{
ID: id,
}
// 创建状态机
task.FSM = fsm.NewFSM(
StatePending, // 初始状态
fsm.Events{ // 定义状态转换规则
{Name: EventAssign, Src: []string{StatePending}, Dst: StateAssigned},
{Name: EventAccept, Src: []string{StateAssigned}, Dst: StateAccepted},
{Name: EventSubmit, Src: []string{StateAccepted}, Dst: StateSubmitted},
{Name: EventApprove, Src: []string{StateSubmitted}, Dst: StateApproved},
{Name: EventReject, Src: []string{StateSubmitted}, Dst: StateRejected},
{Name: EventSettle, Src: []string{StateApproved}, Dst: StateSettled},
// Cancel 事件可以从 Pending 或 Assigned 状态触发
{Name: EventCancel, Src: []string{StatePending, StateAssigned}, Dst: StateCanceled},
},
fsm.Callbacks{ // 定义回调函数
// 通用回调:每次触发事件前执行(通过 e.Cancel() 可以组织内存中实际状态变化)
"before_event": func(_ context.Context, e *fsm.Event) {
if e.Event == EventCancel {
e.Cancel(fmt.Errorf("failed to handle event %s", e.Event))
return
}
fmt.Printf("[Event]Task %s event %s triggered\n", task.ID, e.Event)
},
// 通用回调:每次进入新状态时触发
"enter_state": func(_ context.Context, e *fsm.Event) {
fmt.Printf("[State] Task %s state changed from %s to %s\n", task.ID, e.Src, e.Dst)
// 在这里可以添加通用逻辑,如更新数据库状态
},
// 特定状态回调:进入 Assigned 状态后执行
StateAssigned: func(_ context.Context, e *fsm.Event) {
fmt.Printf("[State] Task %s assigned to user %s\n", task.ID, task.UserID)
// 在这里可以发送通知给被分配者
},
},
)
return task
}
// 任务状态流转方法
func (t *Task) Assign(ctx context.Context, userID string) error {
t.UserID = userID // 可以在事件触发前设置相关信息
return t.FSM.Event(ctx, EventAssign) // 触发 Assign 事件
}
func (t *Task) Accept(ctx context.Context) error {
return t.FSM.Event(ctx, EventAccept)
}
func (t *Task) Submit(ctx context.Context) error {
return t.FSM.Event(ctx, EventSubmit)
}
func (t *Task) Approve(ctx context.Context) error {
return t.FSM.Event(ctx, EventApprove)
}
func (t *Task) Settle(ctx context.Context) error {
return t.FSM.Event(ctx, EventSettle)
}
func (t *Task) Cancel(ctx context.Context) error {
return t.FSM.Event(ctx, EventCancel)
}
// ... 其他事件触发方法 ...