Решение на Concurrent Crawling от Иван Главчев

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

Към профила на Иван Главчев

Резултати

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

Код

package main
import (
//"sync"
"errors"
//"fmt"
"time"
//"strconv"
"io/ioutil"
"net/http"
//"strings"
)
func SeekAndDestroy(callback func(string) bool, chunkedUrlsToCheck <-chan []string, workersCount int) (string, error) {
if workersCount == 0 {
return "", errors.New("gg")
}
if _, open := <-chunkedUrlsToCheck; !open {
return "", errors.New("Closed channel given as argument to the function")
}
if callback == nil {
return "", errors.New("Nil callback")
}
var sem chan struct{}
if workersCount < 3 {
sem = make(chan struct{}, workersCount)
} else {
sem = make(chan struct{}, workersCount - 2)
}
resChan := make(chan string, 13)
errorChan := make(chan error, 17)
go func() {
go func() {
timer := time.NewTimer(time.Second * 15)
<-timer.C
// cancel the function
errorChan <- errors.New("timeout")
}()
for chunk := range chunkedUrlsToCheck {
for i := range chunk {
go func() {
sem <- struct{}{}
defer func() {
<-sem
}()
url := chunk[i]
// http request
timeout := time.Duration(3 * time.Second)
client := http.Client{
Timeout: timeout,
}
response, err := client.Get(url)
if err != nil {
//errorChan <- err
return
}
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
//
return
}
if callback(string(contents)) {
resChan <- url
return
}
}()
}
}
// channel is closed, throw error
errorChan <- errors.New("gg")
}()
select {
case result := <-resChan:
return result, nil
case err := <-errorChan:
return "", err
}
}

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

[/tmp/go-build973169451/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithNegativeWorkersCount -test.timeout=120s]
--- FAIL: TestWithNegativeWorkersCount-2 (1.00 seconds)
	solution_test.go:43: Test exceeded allowed time of 1 seconds: parameter errors should be immediately returned (workersCount is negative)
FAIL
exit status 1
FAIL	_/tmp/d20150111-16649-17bhj2c	1.010s
[/tmp/go-build871292974/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithZeroWorkersCount -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	0.005s
[/tmp/go-build094865362/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithInvalidCallback -test.timeout=120s]
--- FAIL: TestWithInvalidCallback-2 (1.00 seconds)
	solution_test.go:43: Test exceeded allowed time of 1 seconds: parameter errors should be immediately returned (callback is nil)
FAIL
exit status 1
FAIL	_/tmp/d20150111-16649-17bhj2c	1.009s
[/tmp/go-build560912199/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithNilChannel -test.timeout=120s]
--- FAIL: TestWithNilChannel-2 (1.00 seconds)
	solution_test.go:43: Test exceeded allowed time of 1 seconds: parameter errors should be immediately returned (channel is uninitialized)
FAIL
exit status 1
FAIL	_/tmp/d20150111-16649-17bhj2c	1.006s
[/tmp/go-build973485732/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithClosedChannelWhenStarting -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	0.010s
[/tmp/go-build465871388/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithClosedChannelMidway -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	5.008s
[/tmp/go-build304348800/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWhetherGlobalTimeoutIsHandled -test.timeout=120s]
--- FAIL: TestWhetherGlobalTimeoutIsHandled-2 (17.00 seconds)
	solution_test.go:43: Test exceeded allowed time of 17 seconds: the global timeout should have happened in 15 seconds
FAIL
exit status 1
FAIL	_/tmp/d20150111-16649-17bhj2c	17.008s
[/tmp/go-build164605348/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestWithLoremIpsum -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	2.009s
[/tmp/go-build228223709/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestIfTimeoutAndErrorCodesAreHonoured -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	8.007s
[/tmp/go-build696771182/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestRaceCondition -test.timeout=120s]
--- FAIL: TestRaceCondition-2 (5.00 seconds)
	solution_test.go:43: Test exceeded allowed time of 5 seconds: This should have finished in approx. 3 seconds
FAIL
exit status 1
FAIL	_/tmp/d20150111-16649-17bhj2c	5.007s
[/tmp/go-build098315071/_/tmp/d20150111-16649-17bhj2c/_test/d20150111-16649-17bhj2c.test -test.run=TestCloseChannelBeforeFinish -test.timeout=120s]
PASS
ok  	_/tmp/d20150111-16649-17bhj2c	1.006s

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

Иван обнови решението на 10.12.2014 19:45 (преди над 3 години)

+package main
+
+import (
+ //"sync"
+ "errors"
+ //"fmt"
+ "time"
+ //"strconv"
+ "io/ioutil"
+ "net/http"
+ //"strings"
+)
+
+func SeekAndDestroy(callback func(string) bool, chunkedUrlsToCheck <-chan []string, workersCount int) (string, error) {
+ if workersCount == 0 {
+ return "", errors.New("gg")
+ }
+
+ sem := make(chan struct{}, workersCount)
+ resChan := make(chan string, 13)
+ errorChan := make(chan error, 17)
+
+ go func() {
+ go func() {
+ timer := time.NewTimer(time.Second * 15)
+ <-timer.C
+ // cancel the function
+ errorChan <- errors.New("gg")
+ }()
+ for chunk := range chunkedUrlsToCheck {
+ for i := range chunk {
+ go func() {
+ sem <- struct{}{}
+ defer func() {
+ <-sem
+ }()
+
+ url := chunk[i]
+
+ // http request
+ timeout := time.Duration(3 * time.Second)
+ client := http.Client{
+ Timeout: timeout,
+ }
+ response, err := client.Get(url)
+ if err != nil {
+ //errorChan <- err
+ return
+ }
+ defer response.Body.Close()
+ contents, err := ioutil.ReadAll(response.Body)
+ if err != nil {
+ //
+ return
+ }
+
+ if callback(string(contents)) {
+ resChan <- url
+ return
+ }
+ }()
+ }
+ }
+
+ // channel is closed, throw error
+ errorChan <- errors.New("gg")
+ }()
+
+ select {
+ case result := <-resChan:
+ return result, nil
+ case err := <-errorChan:
+ return "", err
+ }
+}

Иван обнови решението на 11.12.2014 16:32 (преди над 3 години)

package main
import (
//"sync"
"errors"
//"fmt"
"time"
//"strconv"
"io/ioutil"
"net/http"
//"strings"
)
func SeekAndDestroy(callback func(string) bool, chunkedUrlsToCheck <-chan []string, workersCount int) (string, error) {
if workersCount == 0 {
return "", errors.New("gg")
}
- sem := make(chan struct{}, workersCount)
+ if _, open := <-chunkedUrlsToCheck; !open {
+ return "", errors.New("Closed channel given as argument to the function")
+ }
+
+ if callback == nil {
+ return "", errors.New("Nil callback")
+ }
+
+ var sem chan struct{}
+ if workersCount < 3 {
+ sem = make(chan struct{}, workersCount)
+ } else {
+ sem = make(chan struct{}, workersCount - 2)
+ }
resChan := make(chan string, 13)
errorChan := make(chan error, 17)
go func() {
go func() {
timer := time.NewTimer(time.Second * 15)
<-timer.C
// cancel the function
- errorChan <- errors.New("gg")
+ errorChan <- errors.New("timeout")
}()
for chunk := range chunkedUrlsToCheck {
for i := range chunk {
go func() {
sem <- struct{}{}
defer func() {
<-sem
}()
url := chunk[i]
// http request
timeout := time.Duration(3 * time.Second)
client := http.Client{
Timeout: timeout,
}
response, err := client.Get(url)
if err != nil {
//errorChan <- err
return
}
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
//
return
}
if callback(string(contents)) {
resChan <- url
return
}
}()
}
}
// channel is closed, throw error
errorChan <- errors.New("gg")
}()
select {
case result := <-resChan:
return result, nil
case err := <-errorChan:
return "", err
}
}