mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-12-15 04:06:35 +08:00
feat: flow design & page query refactor
This commit is contained in:
170
server/internal/flow/application/execution.go
Normal file
170
server/internal/flow/application/execution.go
Normal file
@@ -0,0 +1,170 @@
|
||||
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")
|
||||
}
|
||||
|
||||
// 记录当前节点结束
|
||||
e.hisProcinstOpApp.RecordEnd(ctx, "copmpleted")
|
||||
|
||||
// 下一个节点为空,说明流程已结束
|
||||
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
|
||||
}
|
||||
|
||||
// 节点开始操作记录
|
||||
e.hisProcinstOpApp.RecordStart(ctx)
|
||||
|
||||
// 执行节点逻辑
|
||||
return node.Execute(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user