2025-05-20 21:04:47 +08:00
|
|
|
package application
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"mayfly-go/internal/flow/domain/entity"
|
|
|
|
|
"mayfly-go/internal/flow/domain/repository"
|
|
|
|
|
"mayfly-go/pkg/base"
|
|
|
|
|
"mayfly-go/pkg/errorx"
|
|
|
|
|
"mayfly-go/pkg/eventbus"
|
|
|
|
|
"mayfly-go/pkg/model"
|
|
|
|
|
"mayfly-go/pkg/utils/collx"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Execution interface {
|
|
|
|
|
base.App[*entity.Execution]
|
|
|
|
|
|
|
|
|
|
Init()
|
|
|
|
|
|
|
|
|
|
// CreateExecution 创建执行流(初始化)
|
|
|
|
|
CreateExecution(ctx context.Context, procinst *entity.Procinst) error
|
|
|
|
|
|
|
|
|
|
// ContinueExecution 推进执行流继续执行后续节点
|
|
|
|
|
ContinueExecution(ctx *ExecutionCtx) error
|
|
|
|
|
|
|
|
|
|
// MoveTo 移动执行流到指定节点
|
|
|
|
|
MoveTo(ctx *ExecutionCtx, node *entity.FlowNode) error
|
|
|
|
|
|
|
|
|
|
CreateChildExecution(context.Context, *entity.Execution) (*entity.Execution, error)
|
|
|
|
|
|
|
|
|
|
// CancelExecution 取消流程实例的所有执行流
|
|
|
|
|
CancelExecution(ctx context.Context, procinstId uint64) error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type executionAppImpl struct {
|
|
|
|
|
base.AppImpl[*entity.Execution, repository.Execution]
|
|
|
|
|
|
|
|
|
|
hisProcinstOpApp HisProcinstOp `inject:"T"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ (Execution) = (*executionAppImpl)(nil)
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) Init() {
|
|
|
|
|
nodeBehaviorRegistry.Register(&StartNodeBehavior{})
|
|
|
|
|
nodeBehaviorRegistry.Register(&EndNodeBehavior{})
|
|
|
|
|
nodeBehaviorRegistry.Register(&UserTaskNodeBehavior{})
|
|
|
|
|
|
|
|
|
|
const subId = "ExecutionApp"
|
|
|
|
|
|
|
|
|
|
flowEventBus.Subscribe(EventTopicFlowProcinstCreate, subId, func(ctx context.Context, event *eventbus.Event[any]) error {
|
|
|
|
|
procinst := event.Val.(*entity.Procinst)
|
|
|
|
|
return e.CreateExecution(ctx, procinst)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
flowEventBus.Subscribe(EventTopicFlowProcinstCancel, subId, func(ctx context.Context, event *eventbus.Event[any]) error {
|
|
|
|
|
procinstId := event.Val.(uint64)
|
|
|
|
|
return e.CancelExecution(ctx, procinstId)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) CreateExecution(ctx context.Context, procinst *entity.Procinst) error {
|
|
|
|
|
flowDef := procinst.GetFlowDef()
|
|
|
|
|
startNodes := flowDef.GetNodeByType(FlowNodeTypeStart)
|
|
|
|
|
if len(startNodes) == 0 || len(startNodes) > 1 {
|
|
|
|
|
return errorx.NewBiz("start node not found or more than one")
|
|
|
|
|
}
|
|
|
|
|
startNode := startNodes[0]
|
|
|
|
|
|
|
|
|
|
// 创建执行流
|
|
|
|
|
execution := &entity.Execution{
|
|
|
|
|
ProcinstId: procinst.Id,
|
|
|
|
|
ParentId: 0,
|
|
|
|
|
NodeKey: startNode.Key,
|
|
|
|
|
NodeName: startNode.Name,
|
|
|
|
|
NodeType: startNode.Type,
|
|
|
|
|
State: entity.ExectionStateActive,
|
|
|
|
|
IsConcurrent: -1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return e.Tx(ctx, func(ctx context.Context) error {
|
|
|
|
|
if err := e.Save(ctx, execution); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return e.executeNode(NewExecutionCtx(ctx, procinst, execution))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) ContinueExecution(ctx *ExecutionCtx) error {
|
|
|
|
|
// 合并流程实例与执行流变量,执行流变量优先级高
|
|
|
|
|
vars := collx.MapMerge(ctx.ProcinsVars, ctx.ExecutionVars)
|
|
|
|
|
|
|
|
|
|
nextNode, err := ctx.GetNextNode(vars)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return e.MoveTo(ctx, nextNode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) MoveTo(ctx *ExecutionCtx, nextNode *entity.FlowNode) error {
|
|
|
|
|
execution := ctx.Execution
|
|
|
|
|
if execution == nil {
|
|
|
|
|
return errorx.NewBiz("execution is nil")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录当前节点结束
|
2025-05-24 16:22:54 +08:00
|
|
|
if err := e.hisProcinstOpApp.RecordEnd(ctx, "copmpleted"); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2025-05-20 21:04:47 +08:00
|
|
|
|
|
|
|
|
// 下一个节点为空,说明流程已结束
|
|
|
|
|
if nextNode == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行流推进下一节点,并执行节点逻辑
|
|
|
|
|
execution.NodeKey = nextNode.Key
|
|
|
|
|
execution.NodeName = nextNode.Name
|
|
|
|
|
execution.NodeType = nextNode.Type
|
|
|
|
|
|
|
|
|
|
return e.Tx(ctx, func(c context.Context) error {
|
|
|
|
|
// 更新当前执行流的最新节点信息
|
|
|
|
|
if err := e.Save(c, execution); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return e.executeNode(ctx)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) CreateChildExecution(ctx context.Context, parentExection *entity.Execution) (*entity.Execution, error) {
|
|
|
|
|
execution := &entity.Execution{
|
|
|
|
|
ProcinstId: parentExection.ProcinstId,
|
|
|
|
|
ParentId: parentExection.Id,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return execution, e.Save(ctx, execution)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) CancelExecution(ctx context.Context, procinstId uint64) error {
|
|
|
|
|
executions, err := e.ListByCond(model.NewCond().
|
|
|
|
|
Eq("procinst_id", procinstId).
|
|
|
|
|
In("state", collx.AsArray(entity.ExectionStateActive, entity.ExectionStateSuspended)))
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return e.Tx(ctx, func(ctx context.Context) error {
|
|
|
|
|
for _, execution := range executions {
|
|
|
|
|
execution.State = entity.ExectionStateTerminated
|
|
|
|
|
if err := e.UpdateById(ctx, execution); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *executionAppImpl) executeNode(ctx *ExecutionCtx) error {
|
|
|
|
|
flowNode := ctx.GetFlowNode()
|
|
|
|
|
node, err := nodeBehaviorRegistry.GetNode(flowNode.Type)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 节点开始操作记录
|
2025-05-24 16:22:54 +08:00
|
|
|
if err := e.hisProcinstOpApp.RecordStart(ctx); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2025-05-20 21:04:47 +08:00
|
|
|
|
|
|
|
|
// 执行节点逻辑
|
|
|
|
|
return node.Execute(ctx)
|
|
|
|
|
}
|