Решение на Concurrent Retry Executor от Добромир Иванов

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

Към профила на Добромир Иванов

Резултати

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

Код

package main
func taskRunner(index int, task func() string, retryLimit int, syncChan chan struct{}, resultChan chan struct {
index int
result string
}) {
result := ""
for i := 0; i < retryLimit && result == ""; i++ {
result = task()
resultChan <- struct {
index int
result string
}{index, result}
}
syncChan <- struct{}{}
}
func taskScheduler(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan struct {
index int
result string
}) {
syncChan := make(chan struct{})
tasksRunning := 0
for i, task := range tasks {
go taskRunner(i, task, retryLimit, syncChan, resultChan)
tasksRunning++
if tasksRunning == concurrentLimit {
<-syncChan
tasksRunning--
}
}
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
return
}
for range syncChan {
tasksRunning--
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
}
}
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
resultChan := make(chan struct {
index int
result string
})
go taskScheduler(tasks, concurrentLimit, retryLimit, resultChan)
return resultChan
}

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

PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.003s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.026s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.023s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.004s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.009s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.070s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.293s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.569s
PASS
ok  	_/tmp/d20161115-21147-1q9ejtb	0.203s

История (5 версии и 4 коментара)

Добромир обнови решението на 13.11.2016 18:50 (преди над 1 година)

+package main
+
+type Result struct {
+ index int
+ result string
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan Result {
+ resultChan, limitChan := make(chan Result), make(chan interface{}, concurrentLimit)
+ syncChan := make(chan struct{}, 1)
+ tasksDone := 0
+
+ for i, task := range tasks {
+
+ go func(index int, task func() string) {
+ limitChan <- struct{}{}
+ result := ""
+
+ for i := 0; i < retryLimit && result == ""; i++ {
+ result = task()
+ resultChan <- Result{index, result}
+ }
+ <-limitChan
+
+ syncChan <- struct{}{}
+ tasksDone++
+ if tasksDone == len(tasks) {
+ close(resultChan)
+ }
+ <-syncChan
+ }(i, task)
+ }
+
+ return resultChan
+}

Не се грижиш да се изпълняват последователно задачите - съмнявам се че ти минават и примерните тестове.

Принципно не сме прешодавали именувани типове и бих предпочел ако не ги ползвате

Добромир обнови решението на 15.11.2016 12:42 (преди над 1 година)

package main
-type Result struct {
+func taskRunner(index int, task func() string, retryLimit int, syncChan chan interface{}, resultChan chan struct {
index int
result string
+}) {
+ result := ""
+ for i := 0; i < retryLimit && result == ""; i++ {
+ result = task()
+ resultChan <- struct {
+ index int
+ result string
+ }{index, result}
+ }
+ syncChan <- struct{}{}
}
-func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan Result {
- resultChan, limitChan := make(chan Result), make(chan interface{}, concurrentLimit)
- syncChan := make(chan struct{}, 1)
- tasksDone := 0
+func taskScheduler(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan struct {
+ index int
+ result string
+}) {
+ syncChan := make(chan interface{})
+ tasksRunning := 0
for i, task := range tasks {
+ go taskRunner(i, task, retryLimit, syncChan, resultChan)
+ tasksRunning++
- go func(index int, task func() string) {
- limitChan <- struct{}{}
- result := ""
-
- for i := 0; i < retryLimit && result == ""; i++ {
- result = task()
- resultChan <- Result{index, result}
- }
- <-limitChan
-
- syncChan <- struct{}{}
- tasksDone++
- if tasksDone == len(tasks) {
- close(resultChan)
- }
+ if tasksRunning == concurrentLimit {
<-syncChan
- }(i, task)
+ tasksRunning--
+ }
}
+ for range syncChan {
+ tasksRunning--
+ if tasksRunning == 0 {
+ close(resultChan)
+ close(syncChan)
+ }
+ }
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
+ index int
+ result string
+} {
+ resultChan := make(chan struct {
+ index int
+ result string
+ })
+ go taskScheduler(tasks, concurrentLimit, retryLimit, resultChan)
return resultChan
}

Добромир обнови решението на 15.11.2016 12:46 (преди над 1 година)

package main
func taskRunner(index int, task func() string, retryLimit int, syncChan chan interface{}, resultChan chan struct {
index int
result string
}) {
result := ""
for i := 0; i < retryLimit && result == ""; i++ {
result = task()
resultChan <- struct {
index int
result string
}{index, result}
}
syncChan <- struct{}{}
}
func taskScheduler(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan struct {
index int
result string
}) {
syncChan := make(chan interface{})
tasksRunning := 0
for i, task := range tasks {
go taskRunner(i, task, retryLimit, syncChan, resultChan)
tasksRunning++
if tasksRunning == concurrentLimit {
<-syncChan
tasksRunning--
}
}
for range syncChan {
tasksRunning--
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
}
}
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
resultChan := make(chan struct {
index int
result string
})
go taskScheduler(tasks, concurrentLimit, retryLimit, resultChan)
return resultChan
-}
+}

Добромир обнови решението на 15.11.2016 15:07 (преди над 1 година)

package main
func taskRunner(index int, task func() string, retryLimit int, syncChan chan interface{}, resultChan chan struct {
index int
result string
}) {
result := ""
for i := 0; i < retryLimit && result == ""; i++ {
result = task()
resultChan <- struct {
index int
result string
}{index, result}
}
syncChan <- struct{}{}
}
func taskScheduler(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan struct {
index int
result string
}) {
syncChan := make(chan interface{})
tasksRunning := 0
for i, task := range tasks {
go taskRunner(i, task, retryLimit, syncChan, resultChan)
tasksRunning++
if tasksRunning == concurrentLimit {
<-syncChan
tasksRunning--
}
}
+ if tasksRunning == 0 {
+ close(resultChan)
+ close(syncChan)
+ return
+ }
+
for range syncChan {
tasksRunning--
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
}
}
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
resultChan := make(chan struct {
index int
result string
})
go taskScheduler(tasks, concurrentLimit, retryLimit, resultChan)
return resultChan
}

Добромир обнови решението на 15.11.2016 15:12 (преди над 1 година)

package main
-func taskRunner(index int, task func() string, retryLimit int, syncChan chan interface{}, resultChan chan struct {
+func taskRunner(index int, task func() string, retryLimit int, syncChan chan struct{}, resultChan chan struct {
index int
result string
}) {
result := ""
for i := 0; i < retryLimit && result == ""; i++ {
result = task()
resultChan <- struct {
index int
result string
}{index, result}
}
syncChan <- struct{}{}
}
func taskScheduler(tasks []func() string, concurrentLimit int, retryLimit int, resultChan chan struct {
index int
result string
}) {
- syncChan := make(chan interface{})
+ syncChan := make(chan struct{})
tasksRunning := 0
for i, task := range tasks {
go taskRunner(i, task, retryLimit, syncChan, resultChan)
tasksRunning++
if tasksRunning == concurrentLimit {
<-syncChan
tasksRunning--
}
}
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
return
}
for range syncChan {
tasksRunning--
if tasksRunning == 0 {
close(resultChan)
close(syncChan)
}
}
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
resultChan := make(chan struct {
index int
result string
})
go taskScheduler(tasks, concurrentLimit, retryLimit, resultChan)
return resultChan
}