Решение на Concurrent Retry Executor от Радостина Димова

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

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

Резултати

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

Код

package main
type Result struct {
index int
result string
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan Result {
sem := make(chan struct{}, concurrentLimit)
returnChannel := make(chan Result)
finished := make(chan struct{})
for i := 0; i < concurrentLimit; i++ {
sem <- struct{}{}
}
go func() {
for i, fun := range tasks {
<-sem
go execute(fun, i, retryLimit, returnChannel, sem, finished)
}
for range tasks {
<-finished
}
close(returnChannel)
close(sem)
close(finished)
}()
return returnChannel
}
func execute(f func() string, index int, retryLimit int, returnChannel chan<- Result, sem chan struct{}, finished chan<- struct{}) {
for retryLimit > 0 {
result := f()
returnChannel <- Result{index, result}
if result != "" {
break
}
retryLimit--
}
sem <- struct{}{}
finished <- struct{}{}
}

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

PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.003s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.030s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.033s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.003s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.003s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.121s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.414s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.872s
PASS
ok  	_/tmp/d20161115-21147-xfrs97	0.203s

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

Радостина обнови решението на 10.11.2016 17:19 (преди над 1 година)

+package main
+
+type Result struct {
+ index int
+ result string
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan Result {
+ sem := make(chan struct{}, concurrentLimit)
+ returnChannel := make(chan Result)
+ finished := make(chan struct{})
+
+ for i := 0; i < concurrentLimit; i++ {
+ sem <- struct{}{}
+ }
+ go func() {
+ for i, fun := range tasks {
+ go execute(fun, i, retryLimit, returnChannel, sem, finished)
+ }
+ for range tasks {
+ <-finished
+ }
+ close(returnChannel)
+ close(sem)
+ close(finished)
+ }()
+ return returnChannel
+}
+
+func execute(f func() string, index int, retryLimit int, returnChannel chan<- Result, sem chan struct{}, finished chan<- struct{}) {
+ <-sem
+ for retryLimit > 0 {
+ result := f()
+ returnChannel <- Result{index, result}
+
+ if result != "" {
+ break
+ }
+ retryLimit--
+ }
+ sem <- struct{}{}
+ finished <- struct{}{}
+}

Изглежда добре, но не спазваш част от условието, което не е добре :( . В първото изречение се казва конкурентно и последователно. Конкурентното ти се получава, последователното е на късмет.

Пояснявам че под последователно в случая се има предвид че ако задачите са 5 и трябва да изпълнявам 2 конкурентно, то искаме първо да се изпълнят и върнат първата и втората и когато едната завърши да почне третата и т.н.

първо да се изпълнят и върнат - тогава примера ви има лимит за конкурентност от 2, а първо се връщат 2ра и 3та задача. В този пример също така изглежда сякаш retryLimit е общия брой на опитите, а не броя на повторните опити.

Радостина обнови решението на 11.11.2016 14:52 (преди над 1 година)

package main
type Result struct {
index int
result string
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan Result {
sem := make(chan struct{}, concurrentLimit)
returnChannel := make(chan Result)
finished := make(chan struct{})
for i := 0; i < concurrentLimit; i++ {
sem <- struct{}{}
}
go func() {
for i, fun := range tasks {
+ <-sem
go execute(fun, i, retryLimit, returnChannel, sem, finished)
}
for range tasks {
<-finished
}
close(returnChannel)
close(sem)
close(finished)
}()
return returnChannel
}
func execute(f func() string, index int, retryLimit int, returnChannel chan<- Result, sem chan struct{}, finished chan<- struct{}) {
- <-sem
for retryLimit > 0 {
result := f()
returnChannel <- Result{index, result}
if result != "" {
break
}
retryLimit--
}
sem <- struct{}{}
finished <- struct{}{}
-}
+}

В примера се изпълняват първа и втора конкурентно. Втора връща първа, защото и е с по-малък sleep. Почва трета, защото конкурентния лимит е 2. Трета завършва по бързо отколкото 1-ва си довършва. Обаче се проваля и се пуска пак. Първа завършва и се почва четвърта и т.н.

Ако имаше 5-та която се проваля също и тя щеше да се провали 3 пъти - всяка задача има по три(по точно колкотно сме подали) пъти да се повтори ако се проваля.

Иначе решението ти е работещо, но можеше да не дефинираш тип ;)