Решение на Concurrent Retry Executor от Константин Тодоров

Обратно към всички решения

Към профила на Константин Тодоров

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 9 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
func startTask(task func() string, retryLimit int, index int, resultChan chan<- struct {
index int
result string
}, concurrencyChan chan struct{}) {
retries := 0
result := ""
for retries < retryLimit && result == "" {
retries++
result = task()
resultChan <- struct {
index int
result string
}{index, result}
}
concurrencyChan <- struct{}{}
}
func executeTasks(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan<- struct {
index int
result string
}) {
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 struct {
index int
result string
} {
resultChan := make(chan struct {
index int
result string
}, concurrentLimit)
go func() {
executeTasks(tasks, concurrentLimit, retryLimit, resultChan)
}()
return resultChan
}

Лог от изпълнението

PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.003s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.026s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.030s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.003s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.003s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.071s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.124s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.229s
PASS
ok  	_/tmp/d20161115-21147-1uzx19h	0.203s

История (2 версии и 0 коментара)

Константин обнови решението на 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
+}

Константин обнови решението на 15.11.2016 09:27 (преди над 1 година)

package main
-type funcResult struct {
+func startTask(task func() string, retryLimit int, index int, resultChan chan<- struct {
index int
result string
-}
-
-func startTask(task func() string, retryLimit int, index int, resultChan chan<- funcResult, concurrencyChan chan struct{}) {
+}, concurrencyChan chan struct{}) {
retries := 0
result := ""
for retries < retryLimit && result == "" {
retries++
result = task()
- resultChan <- funcResult{index, result}
+ resultChan <- struct {
+ index int
+ result string
+ }{index, result}
}
concurrencyChan <- struct{}{}
}
-func executeTasks(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan<- funcResult) {
+func executeTasks(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan<- struct {
+ index int
+ result string
+}) {
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)
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
+ index int
+ result string
+} {
+ resultChan := make(chan struct {
+ index int
+ result string
+ }, concurrentLimit)
go func() {
executeTasks(tasks, concurrentLimit, retryLimit, resultChan)
}()
return resultChan
}