You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

executor.go 3.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package exec
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "gitlink.org.cn/cloudream/common/pkgs/future"
  7. "gitlink.org.cn/cloudream/common/utils/lo2"
  8. "gitlink.org.cn/cloudream/common/utils/sync2"
  9. )
  10. type bindingVars struct {
  11. Waittings []Var
  12. Bindeds []Var
  13. Callback *future.SetVoidFuture
  14. }
  15. type Executor struct {
  16. plan Plan
  17. vars map[VarID]Var
  18. bindings []*bindingVars
  19. lock sync.Mutex
  20. store map[string]any
  21. }
  22. func NewExecutor(plan Plan) *Executor {
  23. planning := Executor{
  24. plan: plan,
  25. vars: make(map[VarID]Var),
  26. store: make(map[string]any),
  27. }
  28. return &planning
  29. }
  30. func (s *Executor) Plan() *Plan {
  31. return &s.plan
  32. }
  33. func (s *Executor) Run(ctx context.Context) (map[string]any, error) {
  34. ctx2, cancel := context.WithCancel(ctx)
  35. defer cancel()
  36. err := sync2.ParallelDo(s.plan.Ops, func(o Op, idx int) error {
  37. err := o.Execute(ctx2, s)
  38. s.lock.Lock()
  39. defer s.lock.Unlock()
  40. if err != nil {
  41. cancel()
  42. return fmt.Errorf("%T: %w", o, err)
  43. }
  44. return nil
  45. })
  46. if err != nil {
  47. return nil, err
  48. }
  49. return s.store, nil
  50. }
  51. func (s *Executor) BindVars(ctx context.Context, vs ...Var) error {
  52. s.lock.Lock()
  53. callback := future.NewSetVoid()
  54. binding := &bindingVars{
  55. Callback: callback,
  56. }
  57. for _, v := range vs {
  58. v2 := s.vars[v.GetID()]
  59. if v2 == nil {
  60. binding.Waittings = append(binding.Waittings, v)
  61. continue
  62. }
  63. if err := AssignVar(v2, v); err != nil {
  64. s.lock.Unlock()
  65. return fmt.Errorf("assign var %v to %v: %w", v2.GetID(), v.GetID(), err)
  66. }
  67. binding.Bindeds = append(binding.Bindeds, v)
  68. }
  69. if len(binding.Waittings) == 0 {
  70. s.lock.Unlock()
  71. return nil
  72. }
  73. s.bindings = append(s.bindings, binding)
  74. s.lock.Unlock()
  75. err := callback.Wait(ctx)
  76. s.lock.Lock()
  77. defer s.lock.Unlock()
  78. s.bindings = lo2.Remove(s.bindings, binding)
  79. return err
  80. }
  81. func (s *Executor) PutVars(vs ...Var) {
  82. s.lock.Lock()
  83. defer s.lock.Unlock()
  84. loop:
  85. for _, v := range vs {
  86. for ib, b := range s.bindings {
  87. for iw, w := range b.Waittings {
  88. if w.GetID() != v.GetID() {
  89. continue
  90. }
  91. if err := AssignVar(v, w); err != nil {
  92. b.Callback.SetError(fmt.Errorf("assign var %v to %v: %w", v.GetID(), w.GetID(), err))
  93. // 绑定类型不对,说明生成的执行计划有问题,怎么处理都可以,因为最终会执行失败
  94. continue loop
  95. }
  96. b.Bindeds = append(b.Bindeds, w)
  97. b.Waittings = lo2.RemoveAt(b.Waittings, iw)
  98. if len(b.Waittings) == 0 {
  99. b.Callback.SetVoid()
  100. s.bindings = lo2.RemoveAt(s.bindings, ib)
  101. }
  102. // 绑定成功,继续最外层循环
  103. continue loop
  104. }
  105. }
  106. // 如果没有绑定,则直接放入变量表中
  107. s.vars[v.GetID()] = v
  108. }
  109. }
  110. func (s *Executor) Store(key string, val any) {
  111. s.lock.Lock()
  112. defer s.lock.Unlock()
  113. s.store[key] = val
  114. }
  115. func BindArrayVars[T Var](sw *Executor, ctx context.Context, vs []T) error {
  116. var vs2 []Var
  117. for _, v := range vs {
  118. vs2 = append(vs2, v)
  119. }
  120. return sw.BindVars(ctx, vs2...)
  121. }
  122. func PutArrayVars[T Var](sw *Executor, vs []T) {
  123. var vs2 []Var
  124. for _, v := range vs {
  125. vs2 = append(vs2, v)
  126. }
  127. sw.PutVars(vs2...)
  128. }