Решение на Concurrent Retry Executor от Никола Юруков

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

Към профила на Никола Юруков

Резултати

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

Код

package main
type returnType struct {
index int
result string
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
resultChannel := make(chan struct {
index int
result string
}, len(tasks)*retryLimit)
go retryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
return resultChannel
}
func retryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
index int
result string
}) {
workFinished := make(chan struct{}, len(tasks))
// Start the workers
for i, task := range tasks {
semaphore <- struct{}{}
go retryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
}
// Has everyone finished ?
for i := 0; i < len(tasks); i++ {
<-workFinished
}
close(resultChannel)
}
func retryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
index int
result string
}) {
returnStruct := returnType{taskNumber, ""}
for retryLimit > 0 {
returnStruct.result = task()
resultChannel <- returnStruct
if returnStruct.result != "" {
break
} else {
retryLimit--
}
}
<-semaphore
workFinished <- struct{}{}
}

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

PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.003s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.026s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.028s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.003s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.003s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.071s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.461s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.277s
PASS
ok  	_/tmp/d20161115-21147-zipsn5	0.203s

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

Никола обнови решението на 15.11.2016 06:20 (преди над 1 година)

+package main
+
+import (
+ "fmt"
+ "time"
+)
+
+type returnType struct {
+ index int
+ result string
+}
+
+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!")
+}
+
+func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
+ index int
+ result string
+} {
+ var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
+ resultChannel := make(chan struct {
+ index int
+ result string
+ }, len(tasks)*retryLimit)
+ go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
+ return resultChannel
+}
+
+func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
+ index int
+ result string
+}) {
+ for i, task := range tasks {
+ semaphore <- struct{}{}
+ go RetryingWrapper(task, i, retryLimit, semaphore, resultChannel)
+ }
+ for {
+ if len(semaphore) == 0 {
+ break
+ }
+ }
+ close(resultChannel)
+}
+
+func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
+ index int
+ result string
+}) {
+ returnStruct := returnType{taskNumber, ""}
+ for retryLimit > 0 {
+ returnStruct.result = task()
+ resultChannel <- returnStruct
+ if returnStruct.result != "" {
+ break
+ } else {
+ retryLimit--
+ }
+ }
+ <-semaphore
+}

Никола обнови решението на 15.11.2016 12:18 (преди над 1 година)

package main
import (
"fmt"
"time"
)
type returnType struct {
index int
result string
}
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!")
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
resultChannel := make(chan struct {
index int
result string
}, len(tasks)*retryLimit)
go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
return resultChannel
}
func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
index int
result string
}) {
for i, task := range tasks {
semaphore <- struct{}{}
go RetryingWrapper(task, i, retryLimit, semaphore, resultChannel)
}
for {
if len(semaphore) == 0 {
break
}
+ time.Sleep(100)
}
close(resultChannel)
}
func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
index int
result string
}) {
returnStruct := returnType{taskNumber, ""}
for retryLimit > 0 {
returnStruct.result = task()
resultChannel <- returnStruct
if returnStruct.result != "" {
break
} else {
retryLimit--
}
}
<-semaphore
}

Никола обнови решението на 15.11.2016 12:33 (преди над 1 година)

package main
import (
- "fmt"
- "time"
+ "fmt"
+ "time"
)
type returnType struct {
- index int
- result string
+ index int
+ result string
}
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?"
- }
+ 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!")
+ 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!")
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
- index int
- result string
+ index int
+ result string
} {
- var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
- resultChannel := make(chan struct {
- index int
- result string
- }, len(tasks)*retryLimit)
- go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
- return resultChannel
+ var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
+ resultChannel := make(chan struct {
+ index int
+ result string
+ }, len(tasks)*retryLimit)
+ go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
+ return resultChannel
}
func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
- index int
- result string
+ index int
+ result string
}) {
- for i, task := range tasks {
- semaphore <- struct{}{}
- go RetryingWrapper(task, i, retryLimit, semaphore, resultChannel)
- }
- for {
- if len(semaphore) == 0 {
- break
- }
- time.Sleep(100)
- }
- close(resultChannel)
+ workFinished := make(chan struct{}, len(tasks))
+ // Start the workers
+ for i, task := range tasks {
+ semaphore <- struct{}{}
+ go RetryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
+ }
+ // Has everyone finished ?
+ for i := 0; i < len(tasks); i++ {
+ <-workFinished
+ }
+ close(resultChannel)
}
-func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
- index int
- result string
+func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
+ index int
+ result string
}) {
- returnStruct := returnType{taskNumber, ""}
- for retryLimit > 0 {
- returnStruct.result = task()
- resultChannel <- returnStruct
- if returnStruct.result != "" {
- break
- } else {
- retryLimit--
- }
- }
- <-semaphore
+ returnStruct := returnType{taskNumber, ""}
+ for retryLimit > 0 {
+ returnStruct.result = task()
+ resultChannel <- returnStruct
+ if returnStruct.result != "" {
+ break
+ } else {
+ retryLimit--
+ }
+ }
+ <-semaphore
+ workFinished <- struct{}{}
}

Никола обнови решението на 15.11.2016 12:36 (преди над 1 година)

package main
import (
- "fmt"
- "time"
+ "fmt"
+ "time"
)
type returnType struct {
- index int
- result string
+ index int
+ result string
}
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?"
- }
+ 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!")
+ 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!")
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
- index int
- result string
+ index int
+ result string
} {
- var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
- resultChannel := make(chan struct {
- index int
- result string
- }, len(tasks)*retryLimit)
- go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
- return resultChannel
+ var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
+ resultChannel := make(chan struct {
+ index int
+ result string
+ }, len(tasks)*retryLimit)
+ go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
+ return resultChannel
}
func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
- index int
- result string
+ index int
+ result string
}) {
- workFinished := make(chan struct{}, len(tasks))
- // Start the workers
- for i, task := range tasks {
- semaphore <- struct{}{}
- go RetryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
- }
- // Has everyone finished ?
- for i := 0; i < len(tasks); i++ {
- <-workFinished
- }
- close(resultChannel)
+ workFinished := make(chan struct{}, len(tasks))
+ // Start the workers
+ for i, task := range tasks {
+ semaphore <- struct{}{}
+ go RetryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
+ }
+ // Has everyone finished ?
+ for i := 0; i < len(tasks); i++ {
+ <-workFinished
+ }
+ close(resultChannel)
}
func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
- index int
- result string
+ index int
+ result string
}) {
- returnStruct := returnType{taskNumber, ""}
- for retryLimit > 0 {
- returnStruct.result = task()
- resultChannel <- returnStruct
- if returnStruct.result != "" {
- break
- } else {
- retryLimit--
- }
- }
- <-semaphore
- workFinished <- struct{}{}
+ returnStruct := returnType{taskNumber, ""}
+ for retryLimit > 0 {
+ returnStruct.result = task()
+ resultChannel <- returnStruct
+ if returnStruct.result != "" {
+ break
+ } else {
+ retryLimit--
+ }
+ }
+ <-semaphore
+ workFinished <- struct{}{}
}

Никола обнови решението на 15.11.2016 13:40 (преди над 1 година)

package main
-import (
- "fmt"
- "time"
-)
-
type returnType struct {
index int
result string
-}
-
-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!")
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
resultChannel := make(chan struct {
index int
result string
}, len(tasks)*retryLimit)
go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
return resultChannel
}
func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
index int
result string
}) {
workFinished := make(chan struct{}, len(tasks))
// Start the workers
for i, task := range tasks {
semaphore <- struct{}{}
go RetryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
}
// Has everyone finished ?
for i := 0; i < len(tasks); i++ {
<-workFinished
}
close(resultChannel)
}
func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
index int
result string
}) {
returnStruct := returnType{taskNumber, ""}
for retryLimit > 0 {
returnStruct.result = task()
resultChannel <- returnStruct
if returnStruct.result != "" {
break
} else {
retryLimit--
}
}
<-semaphore
workFinished <- struct{}{}
}

Никола обнови решението на 15.11.2016 17:13 (преди над 1 година)

package main
type returnType struct {
index int
result string
}
func ConcurrentRetryExecutor(tasks []func() string, concurrentLimit int, retryLimit int) <-chan struct {
index int
result string
} {
var semaphore chan struct{} = make(chan struct{}, concurrentLimit)
resultChannel := make(chan struct {
index int
result string
}, len(tasks)*retryLimit)
- go RetryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
+ go retryingWrapperParent(tasks, retryLimit, semaphore, resultChannel)
return resultChannel
}
-func RetryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
+func retryingWrapperParent(tasks []func() string, retryLimit int, semaphore chan struct{}, resultChannel chan struct {
index int
result string
}) {
workFinished := make(chan struct{}, len(tasks))
// Start the workers
for i, task := range tasks {
semaphore <- struct{}{}
- go RetryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
+ go retryingWrapper(task, i, retryLimit, semaphore, workFinished, resultChannel)
}
// Has everyone finished ?
for i := 0; i < len(tasks); i++ {
<-workFinished
}
close(resultChannel)
}
-func RetryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
+func retryingWrapper(task func() string, taskNumber int, retryLimit int, semaphore chan struct{}, workFinished chan struct{}, resultChannel chan struct {
index int
result string
}) {
returnStruct := returnType{taskNumber, ""}
for retryLimit > 0 {
returnStruct.result = task()
resultChannel <- returnStruct
if returnStruct.result != "" {
break
} else {
retryLimit--
}
}
<-semaphore
workFinished <- struct{}{}
}