Run runs a list of functions returns the results
(ctx context.Context, maxConcurrency int, tasks ...Func)
| 92 | |
| 93 | // Run runs a list of functions returns the results |
| 94 | func Run(ctx context.Context, maxConcurrency int, tasks ...Func) ([]Result, error) { |
| 95 | var wg sync.WaitGroup |
| 96 | |
| 97 | resultsChan := make(chan Result, len(tasks)) |
| 98 | taskChan := make(chan Func, len(tasks)) |
| 99 | |
| 100 | localCtx, cancelCtx := context.WithCancel(ctx) |
| 101 | defer cancelCtx() |
| 102 | |
| 103 | runTask := func() { |
| 104 | defer wg.Done() |
| 105 | |
| 106 | for fn := range taskChan { |
| 107 | result, err := fn(localCtx) |
| 108 | resultsChan <- Result{Result: result, Err: err} |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // Set maxConcurrency to the number of tasks if zero or negative |
| 113 | if maxConcurrency <= 0 { |
| 114 | maxConcurrency = len(tasks) |
| 115 | } |
| 116 | |
| 117 | // Start worker goroutines |
| 118 | for range maxConcurrency { |
| 119 | wg.Add(1) |
| 120 | go runTask() |
| 121 | } |
| 122 | |
| 123 | // Add tasks to the task channel |
| 124 | for _, fn := range tasks { |
| 125 | taskChan <- fn |
| 126 | } |
| 127 | |
| 128 | // Close the task channel to signal workers to stop when all tasks are done |
| 129 | close(taskChan) |
| 130 | |
| 131 | // Wait for all workers to complete |
| 132 | wg.Wait() |
| 133 | close(resultsChan) |
| 134 | |
| 135 | // Collect the results and cancel on error |
| 136 | results := make([]Result, 0, len(tasks)) |
| 137 | for r := range resultsChan { |
| 138 | if r.Err != nil { |
| 139 | cancelCtx() |
| 140 | |
| 141 | return nil, r.Err |
| 142 | } |
| 143 | |
| 144 | results = append(results, r) |
| 145 | } |
| 146 | |
| 147 | return results, nil |
| 148 | } |
no test coverage detected