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.3 kB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package exec
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "github.com/hashicorp/go-multierror"
  7. "gitlink.org.cn/cloudream/common/pkgs/future"
  8. "gitlink.org.cn/cloudream/common/utils/lo2"
  9. )
  10. type binding struct {
  11. ID VarID
  12. Callback *future.SetValueFuture[VarValue]
  13. }
  14. type freeVar struct {
  15. ID VarID
  16. Value VarValue
  17. }
  18. type Executor struct {
  19. plan Plan
  20. vars map[VarID]freeVar
  21. bindings []*binding
  22. lock sync.Mutex
  23. store map[string]VarValue
  24. }
  25. func NewExecutor(plan Plan) *Executor {
  26. planning := Executor{
  27. plan: plan,
  28. vars: make(map[VarID]freeVar),
  29. store: make(map[string]VarValue),
  30. }
  31. return &planning
  32. }
  33. func (s *Executor) Plan() *Plan {
  34. return &s.plan
  35. }
  36. func (s *Executor) Run(ctx *ExecContext) (map[string]VarValue, error) {
  37. c, cancel := context.WithCancel(ctx.Context)
  38. ctx = &ExecContext{
  39. Context: c,
  40. Values: ctx.Values,
  41. }
  42. defer cancel()
  43. err := s.runOps(s.plan.Ops, ctx, cancel)
  44. if err != nil {
  45. return nil, err
  46. }
  47. return s.store, nil
  48. }
  49. func (s *Executor) runOps(ops []Op, ctx *ExecContext, cancel context.CancelFunc) error {
  50. lock := sync.Mutex{}
  51. var err error
  52. var wg sync.WaitGroup
  53. wg.Add(len(ops))
  54. for i, arg := range ops {
  55. go func(arg Op, index int) {
  56. defer wg.Done()
  57. if e := arg.Execute(ctx, s); e != nil {
  58. lock.Lock()
  59. // 尽量不记录 Canceled 错误,除非没有其他错误
  60. if err == nil {
  61. err = e
  62. } else if err == context.Canceled {
  63. err = e
  64. } else if e != context.Canceled {
  65. err = multierror.Append(err, e)
  66. }
  67. lock.Unlock()
  68. cancel()
  69. }
  70. }(arg, i)
  71. }
  72. wg.Wait()
  73. return err
  74. }
  75. func (s *Executor) BindVar(ctx context.Context, id VarID) (VarValue, error) {
  76. s.lock.Lock()
  77. gv, ok := s.vars[id]
  78. if ok {
  79. delete(s.vars, id)
  80. s.lock.Unlock()
  81. return gv.Value, nil
  82. }
  83. callback := future.NewSetValue[VarValue]()
  84. s.bindings = append(s.bindings, &binding{
  85. ID: id,
  86. Callback: callback,
  87. })
  88. s.lock.Unlock()
  89. return callback.Wait(ctx)
  90. }
  91. func (s *Executor) PutVar(id VarID, value VarValue) *Executor {
  92. s.lock.Lock()
  93. defer s.lock.Unlock()
  94. for ib, b := range s.bindings {
  95. if b.ID != id {
  96. continue
  97. }
  98. b.Callback.SetValue(value)
  99. s.bindings = lo2.RemoveAt(s.bindings, ib)
  100. return s
  101. }
  102. // 如果没有绑定,则直接放入变量表中
  103. s.vars[id] = freeVar{ID: id, Value: value}
  104. return s
  105. }
  106. func (s *Executor) Store(key string, val VarValue) {
  107. s.lock.Lock()
  108. defer s.lock.Unlock()
  109. s.store[key] = val
  110. }
  111. func BindVar[T VarValue](e *Executor, ctx context.Context, id VarID) (T, error) {
  112. v, err := e.BindVar(ctx, id)
  113. if err != nil {
  114. var def T
  115. return def, err
  116. }
  117. ret, ok := v.(T)
  118. if !ok {
  119. var def T
  120. return def, fmt.Errorf("binded var %v is %T, not %T", id, v, def)
  121. }
  122. return ret, nil
  123. }
  124. func BindArray[T VarValue](e *Executor, ctx context.Context, ids []VarID) ([]T, error) {
  125. ret := make([]T, len(ids))
  126. for i := range ids {
  127. v, err := e.BindVar(ctx, ids[i])
  128. if err != nil {
  129. return nil, err
  130. }
  131. v2, ok := v.(T)
  132. if !ok {
  133. var def T
  134. return nil, fmt.Errorf("binded var %v is %T, not %T", ids[i], v, def)
  135. }
  136. ret[i] = v2
  137. }
  138. return ret, nil
  139. }
  140. func PutArray[T VarValue](e *Executor, ids []VarID, values []T) {
  141. for i := range ids {
  142. e.PutVar(ids[i], values[i])
  143. }
  144. }