Константин обнови решението на 11.11.2016 23:24 (преди над 1 година)
+package main
+
+type funcResult struct {
+ index int
+ result string
+}
+
+func startTask(task func() string, retryLimit int, index int, resultChan chan<- funcResult, concurrencyChan chan struct{}) {
+ retries := 0
+ result := ""
+ for retries < retryLimit && result == "" {
+ retries++
+ result = task()
+ resultChan <- funcResult{index, result}
+ }
+
+ concurrencyChan <- struct{}{}
+}
+
+func executeTasks(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan<- funcResult) {
+ currentlyStarted := 0
+ concurrencyChan := make(chan struct{}, concurrentLimit+1)
+
+ for index, task := range tasks {
+ if currentlyStarted >= concurrentLimit {
+ <-concurrencyChan
+ currentlyStarted--
+ }
+ currentlyStarted++
+ go startTask(task, retryLimit, index, resultChan, concurrencyChan)
+ }
+
+ // Wait for all currentlyStarted tasks to finish
+ for i := 0; i < currentlyStarted; i++ {
+ <-concurrencyChan
+ }
+
+ close(resultChan)
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan funcResult {
+ resultChan := make(chan funcResult, concurrentLimit)
+ go func() {
+ executeTasks(tasks, concurrentLimit, retryLimit, resultChan)
+ }()
+
+ return resultChan
+}