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

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

Към профила на Теодора Иванова

Резултати

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

Код

package main
import (
"fmt"
"sync"
"time"
)
func ConcurrentRetryExecutor(tasks []func() string,
concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
j, k := 0, 0
var wg sync.WaitGroup
type res struct {
index int
result string
}
results := make(chan struct {
index int
result string
}, (len(tasks) + retryLimit))
for i := range tasks {
wg.Add(1)
r := res{i, tasks[i]()}
if r.result != "" {
go func() {
defer wg.Done()
results <- r
}()
} else {
k = i
go func() {
defer wg.Done()
for j < retryLimit {
results <- res{k, tasks[k]()}
j++
}
}()
}
}
go func() {
wg.Wait()
close(results)
}()
return results
}
func main() {
first := func() string {
time.Sleep(2 * time.Second)
return "first"
}
second := func() string {
time.Sleep(1 * time.Second)
return "second"
}
third := func() string {
time.Sleep(600 * time.Millisecond)
return "" // always a failure :(
}
fourth := func() string {
time.Sleep(700 * time.Millisecond)
return "am I last?"
}
fmt.Println("Starting concurrent executor!")
tasks := []func() string{first, second, third, fourth}
results := ConcurrentRetryExecutor(tasks, 2, 3)
for result := range results {
if result.result == "" {
fmt.Printf("Task %d returned an error!\n", result.index+1)
} else {
fmt.Printf("Task %d successfully returned '%s'\n", result.index+1, result.result)
}
}
fmt.Println("All done!")
}

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

panic: test timed out after 1s

goroutine 7 [running]:
panic(0x4ed2e0, 0xc420010620)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200700c0, 0x519db2, 0x1b, 0x525590, 0xc42003bd30)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200700c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200700c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc420010600, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc4200105c0, 0x2, 0x2, 0xa, 0x5, 0x2)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420070180, 0x2, 0xa, 0x5, 0x525588)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.TestLessTaskThanConcurrency(0xc420070180)
	/tmp/d20161115-21147-eulcct/solution_test.go:109 +0x52
testing.tRunner(0xc420070180, 0x525590)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.005s
panic: test timed out after 1s

goroutine 7 [running]:
panic(0x4ed2e0, 0xc420010600)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200720c0, 0x518a94, 0x15, 0x525530, 0xc42003bd01)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200720c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200720c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc4200105e0, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc420090000, 0x400, 0x400, 0x1, 0x5, 0x400)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420072180, 0x400, 0x1, 0x5, 0x525528)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.TestBasic1Concurrency(0xc420072180)
	/tmp/d20161115-21147-eulcct/solution_test.go:118 +0x52
testing.tRunner(0xc420072180, 0x525530)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.005s
panic: test timed out after 1s

goroutine 17 [running]:
panic(0x4ed2e0, 0xc42012c010)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200720c0, 0x518da3, 0x16, 0x525520, 0xc42003bd01)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200720c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200720c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc4200105f0, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc4200a2000, 0x800, 0x800, 0xa, 0x5, 0x800)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420072180, 0x800, 0xa, 0x5, 0x525518)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.TestBasic10Concurrency(0xc420072180)
	/tmp/d20161115-21147-eulcct/solution_test.go:127 +0x52
testing.tRunner(0xc420072180, 0x525520)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.005s
panic: test timed out after 1s

goroutine 7 [running]:
panic(0x4ed2e0, 0xc420010620)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200700c0, 0x5196fa, 0x19, 0x525548, 0xc42003bd01)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200700c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200700c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc420010600, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc4200741e0, 0x14, 0x14, 0x1, 0x5, 0x14)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420070180, 0x14, 0x1, 0x5, 0xc420040ed8)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.testBasicFail(0xc420070180, 0x14, 0x1, 0x5)
	/tmp/d20161115-21147-eulcct/solution_test.go:164 +0xf5
_/tmp/d20161115-21147-eulcct.TestBasicFail1Concurrency(0xc420070180)
	/tmp/d20161115-21147-eulcct/solution_test.go:131 +0x46
testing.tRunner(0xc420070180, 0x525548)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.005s
panic: test timed out after 1s

goroutine 7 [running]:
panic(0x4ed2e0, 0xc420010630)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200700c0, 0x519a83, 0x1a, 0x525540, 0xc42003bd01)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200700c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200700c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc420010610, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc4200741e0, 0x14, 0x14, 0xa, 0x5, 0x14)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420070180, 0x14, 0xa, 0x5, 0xc420040ed8)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.testBasicFail(0xc420070180, 0x14, 0xa, 0x5)
	/tmp/d20161115-21147-eulcct/solution_test.go:164 +0xf5
_/tmp/d20161115-21147-eulcct.TestBasicFail10Concurrency(0xc420070180)
	/tmp/d20161115-21147-eulcct/solution_test.go:135 +0x46
testing.tRunner(0xc420070180, 0x525540)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.005s
panic: test timed out after 1s

goroutine 7 [running]:
panic(0x4ed2e0, 0xc420010640)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:918 +0x10b
created by time.goFunc
	/usr/local/go/src/time/sleep.go:154 +0x44

goroutine 1 [chan receive]:
testing.(*T).Run(0xc4200700c0, 0x51a1a2, 0x1c, 0x525538, 0xc42003bd01)
	/usr/local/go/src/testing/testing.go:647 +0x316
testing.RunTests.func1(0xc4200700c0)
	/usr/local/go/src/testing/testing.go:793 +0x6d
testing.tRunner(0xc4200700c0, 0xc42003be20)
	/usr/local/go/src/testing/testing.go:610 +0x81
testing.RunTests(0x5255c8, 0x5a2320, 0x9, 0x9, 0x517266)
	/usr/local/go/src/testing/testing.go:799 +0x2f5
testing.(*M).Run(0xc42003bee8, 0xc420010510)
	/usr/local/go/src/testing/testing.go:743 +0x85
main.main()
	_/tmp/d20161115-21147-eulcct/_test/_testmain.go:72 +0xc6

goroutine 6 [chan send]:
_/tmp/d20161115-21147-eulcct.generateTaskFunc.func1(0xc420010620, 0x1)
	/tmp/d20161115-21147-eulcct/solution_test.go:16 +0x4d
_/tmp/d20161115-21147-eulcct.ConcurrentRetryExecutor(0xc420098000, 0x1400, 0x1400, 0x400, 0x3, 0x1400)
	/tmp/d20161115-21147-eulcct/solution.go:26 +0x10c
_/tmp/d20161115-21147-eulcct.testBasic(0xc420070180, 0x1400, 0x400, 0x3, 0xc420040ed8)
	/tmp/d20161115-21147-eulcct/solution_test.go:53 +0xcb
_/tmp/d20161115-21147-eulcct.testBasicFail(0xc420070180, 0x1400, 0x400, 0x3)
	/tmp/d20161115-21147-eulcct/solution_test.go:164 +0xf5
_/tmp/d20161115-21147-eulcct.TestBasicFail1024Concurrency(0xc420070180)
	/tmp/d20161115-21147-eulcct/solution_test.go:139 +0x46
testing.tRunner(0xc420070180, 0x525538)
	/usr/local/go/src/testing/testing.go:610 +0x81
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:646 +0x2ec
exit status 2
FAIL	_/tmp/d20161115-21147-eulcct	1.006s
PASS
ok  	_/tmp/d20161115-21147-eulcct	0.160s
PASS
ok  	_/tmp/d20161115-21147-eulcct	0.457s
--- FAIL: TestExampleSimpleScenario (0.20s)
	solution_test.go:296: Expected the second result to be an error from the lazy dog but received {index:1 result:woof}
	solution_test.go:302: Expected the channel to be closed, instead received {index:1 result:woof}
FAIL
exit status 1
FAIL	_/tmp/d20161115-21147-eulcct	0.203s

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

Теодора обнови решението на 15.11.2016 17:19 (преди над 1 година)

+package main
+
+import (
+ "fmt"
+ "sync"
+ "time"
+)
+
+func ConcurrentRetryExecutor(tasks []func() string,
+ concurrentLimit int, retryLimit int) <-chan struct {
+ index int
+ result string
+} {
+ j, k := 0, 0
+ var wg sync.WaitGroup
+ type res struct {
+ index int
+ result string
+ }
+ results := make(chan struct {
+ index int
+ result string
+ }, (len(tasks) + retryLimit))
+ for i := range tasks {
+ wg.Add(1)
+ r := res{i, tasks[i]()}
+ if r.result != "" {
+ go func() {
+ defer wg.Done()
+ results <- r
+ }()
+ } else {
+ k = i
+ go func() {
+ defer wg.Done()
+ for j < retryLimit {
+ results <- res{k, tasks[k]()}
+ j++
+ }
+ }()
+ }
+ }
+ go func() {
+ wg.Wait()
+ close(results)
+ }()
+ return results
+}
+
+func main() {
+
+ first := func() string {
+ time.Sleep(2 * time.Second)
+ return "first"
+ }
+ second := func() string {
+ time.Sleep(1 * time.Second)
+ return "second"
+ }
+ third := func() string {
+ time.Sleep(600 * time.Millisecond)
+ return "" // always a failure :(
+ }
+ fourth := func() string {
+ time.Sleep(700 * time.Millisecond)
+ return "am I last?"
+ }
+
+ fmt.Println("Starting concurrent executor!")
+ tasks := []func() string{first, second, third, fourth}
+ results := ConcurrentRetryExecutor(tasks, 2, 3)
+ for result := range results {
+ if result.result == "" {
+ fmt.Printf("Task %d returned an error!\n", result.index+1)
+ } else {
+ fmt.Printf("Task %d successfully returned '%s'\n", result.index+1, result.result)
+ }
+ }
+ fmt.Println("All done!")
+}