loop.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package flow
  2. import (
  3. "errors"
  4. "fmt"
  5. "git.sxidc.com/go-tools/utils/pipeline/component"
  6. "github.com/mitchellh/mapstructure"
  7. )
  8. const (
  9. TypeLoop = "loop"
  10. )
  11. type LoopBuildParams struct {
  12. ConditionComponent *SubComponentBuildParams `mapstructure:"condition" structs:"condition"`
  13. SubComponent *SubComponentBuildParams `mapstructure:"sub" structs:"sub"`
  14. }
  15. func (params *LoopBuildParams) Check() error {
  16. if params.ConditionComponent == nil {
  17. return errors.New(TypeLoop + "流程的条件组件参数为空")
  18. }
  19. if params.SubComponent == nil {
  20. return errors.New(TypeLoop + "流程的子组件参数为空")
  21. }
  22. err := params.ConditionComponent.Check(TypeLoop)
  23. if err != nil {
  24. return err
  25. }
  26. err = params.SubComponent.Check(TypeLoop)
  27. if err != nil {
  28. return err
  29. }
  30. if params.ConditionComponent.Name == params.SubComponent.Name {
  31. return fmt.Errorf("流程中存在同名的组件: condition: %s flow: %s",
  32. params.ConditionComponent.Name, params.SubComponent.Name)
  33. }
  34. return nil
  35. }
  36. type Loop struct {
  37. component.BaseComponent
  38. ConditionComponent component.Component
  39. SubComponent component.Component
  40. }
  41. func (f *Loop) Run(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
  42. return f.OnRun(globalRunParams, dynamicParams,
  43. func(globalRunParams *component.GlobalRunParams, dynamicParams map[string]any) (any, error) {
  44. lastResult := globalRunParams.GetLastResult()
  45. var conditionDynamicParamsMap map[string]any
  46. conditionDynamicParams, ok := dynamicParams[f.ConditionComponent.GetName()]
  47. if ok {
  48. innerConditionDynamicParamsMap, ok := conditionDynamicParams.(map[string]any)
  49. if !ok {
  50. return nil, errors.New(TypeLoop + "流程" + f.GetName() + "的条件组件" + f.ConditionComponent.GetName() + "动态参数类型错误")
  51. }
  52. conditionDynamicParamsMap = innerConditionDynamicParamsMap
  53. }
  54. var subDynamicParamsMap map[string]any
  55. subDynamicParams, ok := dynamicParams[f.SubComponent.GetName()]
  56. if ok {
  57. innerSubDynamicParamsMap, ok := subDynamicParams.(map[string]any)
  58. if !ok {
  59. return nil, errors.New(TypeLoop + "流程" + f.GetName() + "的子组件" + f.SubComponent.GetName() + "动态参数类型错误")
  60. }
  61. subDynamicParamsMap = innerSubDynamicParamsMap
  62. }
  63. condition, err := f.runConditionComponent(globalRunParams, conditionDynamicParamsMap)
  64. if err != nil {
  65. return nil, err
  66. }
  67. if !condition {
  68. return lastResult, nil
  69. }
  70. var result any
  71. for condition {
  72. innerResult, err := f.SubComponent.Run(globalRunParams, subDynamicParamsMap)
  73. if err != nil {
  74. return nil, err
  75. }
  76. innerCondition, err := f.runConditionComponent(globalRunParams, conditionDynamicParamsMap)
  77. if err != nil {
  78. return nil, err
  79. }
  80. condition = innerCondition
  81. result = innerResult
  82. }
  83. return result, nil
  84. })
  85. }
  86. func (f *Loop) runConditionComponent(globalRunParams *component.GlobalRunParams, conditionDynamicParamsMap map[string]any) (bool, error) {
  87. conditionResult, err := f.ConditionComponent.Run(globalRunParams, conditionDynamicParamsMap)
  88. if err != nil {
  89. return false, err
  90. }
  91. condition, ok := conditionResult.(bool)
  92. if !ok {
  93. return false, errors.New(TypeLoop + "流程的条件子组件返回结果应当为bool")
  94. }
  95. return condition, nil
  96. }
  97. type LoopBuilder struct{}
  98. func (builder *LoopBuilder) ProductType() string {
  99. return TypeLoop
  100. }
  101. func (builder *LoopBuilder) Build(name string, buildParams map[string]any, runParams map[string]any) (component.Component, error) {
  102. if buildParams == nil || len(buildParams) == 0 {
  103. return nil, errors.New(TypeLoop + "流程没有传递构建参数")
  104. }
  105. flowBuildParams := new(LoopBuildParams)
  106. err := mapstructure.Decode(buildParams, flowBuildParams)
  107. if err != nil {
  108. return nil, errors.New(TypeLoop + "流程构建参数Decode失败: " + err.Error())
  109. }
  110. err = flowBuildParams.Check()
  111. if err != nil {
  112. return nil, err
  113. }
  114. conditionFlow, err := flowBuildParams.ConditionComponent.BuildComponent()
  115. if err != nil {
  116. return nil, err
  117. }
  118. subFlow, err := flowBuildParams.SubComponent.BuildComponent()
  119. if err != nil {
  120. return nil, err
  121. }
  122. return &Loop{
  123. BaseComponent: *component.NewBaseComponent(TypeLoop, name, runParams),
  124. ConditionComponent: conditionFlow,
  125. SubComponent: subFlow,
  126. }, nil
  127. }