Решение на HTTP сваляч от Ралица Великова

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

Към профила на Ралица Великова

Резултати

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

Код

package main
import (
"container/ring"
//"sync"
)
type Request interface {
ID() string
Run() (result interface{}, err error)
Cacheable() bool
SetResult(result interface{}, err error)
}
type Requester interface {
AddRequest(request Request)
Stop()
}
const (
Working = iota
Stopped
)
type RequestHandler struct {
requests chan Request
working int
sem chan struct{}
cache *ring.Ring
running map[string]bool
// waitgroup sync.WaitGroup
}
type CacheElement struct {
Id string
Result interface{}
Err error
}
func NewRequester(cacheSize int, throttleSize int) Requester {
requestChannel := make(chan Request)
cache := ring.New(cacheSize)
running := make(map[string]bool)
requester := RequestHandler{requests: requestChannel, working: Working, cache: cache, running: running}
requester.sem = make(chan struct{})
//requester.waitgroup.Add(throttleSize)
go func() {
for request := range requester.requests {
ready := false
requester.cache.Do(func(cacheElement interface{}) {
element, _ := cacheElement.(CacheElement)
if element.Id == request.ID() {
request.SetResult(element.Result, element.Err)
ready = true
}
})
if ready {
continue
}
if requester.running[request.ID()] {
go func() {
requester.requests <- request
}()
continue
}
requester.running[request.ID()] = true
result, err := request.Run()
requester.running[request.ID()] = false
if request.Cacheable() {
requester.cache = requester.cache.Next()
cacheElement := CacheElement{}
cacheElement.Id = request.ID()
cacheElement.Result, cacheElement.Err = result, err
requester.cache.Value = cacheElement
}
}
requester.sem <- struct{}{}
}()
return &requester
}
func (r *RequestHandler) AddRequest(request Request) {
if r.working == Working {
r.requests <- request
}
}
func (r *RequestHandler) Stop() {
r.working = Stopped
//requester.waitgroup.Wait()
close(r.requests)
<-r.sem
}

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

PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.003s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.003s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.103s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.003s
panic: test timed out after 1s

goroutine 3 [running]:
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:703 +0x132
created by time.goFunc
	/usr/local/go/src/time/sleep.go:129 +0x3a

goroutine 1 [chan receive]:
testing.RunTests(0x5e12e8, 0x66ee20, 0xd, 0xd, 0x1)
	/usr/local/go/src/testing/testing.go:562 +0x8ad
testing.(*M).Run(0xc82003fef8, 0xc820062510)
	/usr/local/go/src/testing/testing.go:494 +0x70
main.main()
	_/tmp/d20160101-5892-3qo00n/_test/_testmain.go:78 +0x116

goroutine 20 [chan receive]:
_/tmp/d20160101-5892-3qo00n.TestRequestsAreRunAsyncly(0xc8200a4000)
	/tmp/d20160101-5892-3qo00n/solution_test.go:190 +0x586
testing.tRunner(0xc8200a4000, 0x66ee80)
	/usr/local/go/src/testing/testing.go:456 +0x98
created by testing.RunTests
	/usr/local/go/src/testing/testing.go:561 +0x86d

goroutine 21 [chan receive]:
_/tmp/d20160101-5892-3qo00n.TestRequestsAreRunAsyncly.func1(0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:171 +0xb1
_/tmp/d20160101-5892-3qo00n.(*request).Run(0xc8200663f0, 0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:37 +0xa5
_/tmp/d20160101-5892-3qo00n.NewRequester.func1(0xc8200663c0)
	/tmp/d20160101-5892-3qo00n/solution.go:77 +0x254
created by _/tmp/d20160101-5892-3qo00n.NewRequester
	/tmp/d20160101-5892-3qo00n/solution.go:92 +0x16d

goroutine 23 [chan send]:
_/tmp/d20160101-5892-3qo00n.(*RequestHandler).AddRequest(0xc8200663c0, 0x7f0f430a1550, 0xc820066450)
	/tmp/d20160101-5892-3qo00n/solution.go:99 +0x58
created by _/tmp/d20160101-5892-3qo00n.TestRequestsAreRunAsyncly
	/tmp/d20160101-5892-3qo00n/solution_test.go:189 +0x563
exit status 2
FAIL	_/tmp/d20160101-5892-3qo00n	1.006s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.043s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.003s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.063s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.053s
panic: send on closed channel

goroutine 10 [running]:
_/tmp/d20160101-5892-3qo00n.(*RequestHandler).AddRequest(0xc82000a4b0, 0x7fd20e64c578, 0xc82000a540)
	/tmp/d20160101-5892-3qo00n/solution.go:99 +0x58
created by _/tmp/d20160101-5892-3qo00n.TestStopWithQueue
	/tmp/d20160101-5892-3qo00n/solution_test.go:442 +0x6bb

goroutine 1 [chan receive]:
testing.RunTests(0x5e12e8, 0x66ee20, 0xd, 0xd, 0x1)
	/usr/local/go/src/testing/testing.go:562 +0x8ad
testing.(*M).Run(0xc82003fef8, 0xc820010650)
	/usr/local/go/src/testing/testing.go:494 +0x70
main.main()
	_/tmp/d20160101-5892-3qo00n/_test/_testmain.go:78 +0x116

goroutine 6 [sleep]:
time.Sleep(0x1312d00)
	/usr/local/go/src/runtime/time.go:59 +0xf9
_/tmp/d20160101-5892-3qo00n.TestStopWithQueue(0xc82008c000)
	/tmp/d20160101-5892-3qo00n/solution_test.go:450 +0x73e
testing.tRunner(0xc82008c000, 0x66eef8)
	/usr/local/go/src/testing/testing.go:456 +0x98
created by testing.RunTests
	/usr/local/go/src/testing/testing.go:561 +0x86d

goroutine 7 [chan receive]:
_/tmp/d20160101-5892-3qo00n.TestStopWithQueue.func1(0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:410 +0x68
_/tmp/d20160101-5892-3qo00n.(*request).Run(0xc82000a4e0, 0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:37 +0xa5
_/tmp/d20160101-5892-3qo00n.NewRequester.func1(0xc82000a4b0)
	/tmp/d20160101-5892-3qo00n/solution.go:77 +0x254
created by _/tmp/d20160101-5892-3qo00n.NewRequester
	/tmp/d20160101-5892-3qo00n/solution.go:92 +0x16d

goroutine 17 [chan receive]:
_/tmp/d20160101-5892-3qo00n.(*RequestHandler).Stop(0xc82000a4b0)
	/tmp/d20160101-5892-3qo00n/solution.go:107 +0x53
_/tmp/d20160101-5892-3qo00n.TestStopWithQueue.func3(0xc82001e420, 0x7fd20e64c548, 0xc82000a4b0, 0xc82001e480)
	/tmp/d20160101-5892-3qo00n/solution_test.go:446 +0x35
created by _/tmp/d20160101-5892-3qo00n.TestStopWithQueue
	/tmp/d20160101-5892-3qo00n/solution_test.go:448 +0x70e

goroutine 9 [runnable]:
_/tmp/d20160101-5892-3qo00n.(*RequestHandler).AddRequest(0xc82000a4b0, 0x7fd20e64c578, 0xc82000a510)
	/tmp/d20160101-5892-3qo00n/solution.go:99 +0x58
created by _/tmp/d20160101-5892-3qo00n.TestStopWithQueue
	/tmp/d20160101-5892-3qo00n/solution_test.go:441 +0x646
exit status 2
FAIL	_/tmp/d20160101-5892-3qo00n	0.027s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.033s
PASS
ok  	_/tmp/d20160101-5892-3qo00n	0.053s
panic: test timed out after 1s

goroutine 17 [running]:
testing.startAlarm.func1()
	/usr/local/go/src/testing/testing.go:703 +0x132
created by time.goFunc
	/usr/local/go/src/time/sleep.go:129 +0x3a

goroutine 1 [chan receive]:
testing.RunTests(0x5e12e8, 0x66ee20, 0xd, 0xd, 0x1)
	/usr/local/go/src/testing/testing.go:562 +0x8ad
testing.(*M).Run(0xc82003fef8, 0xc820010650)
	/usr/local/go/src/testing/testing.go:494 +0x70
main.main()
	_/tmp/d20160101-5892-3qo00n/_test/_testmain.go:78 +0x116

goroutine 6 [chan receive]:
_/tmp/d20160101-5892-3qo00n.TestStopWithQueueFromForum(0xc82008e000)
	/tmp/d20160101-5892-3qo00n/solution_test.go:614 +0xa5c
testing.tRunner(0xc82008e000, 0x66ef40)
	/usr/local/go/src/testing/testing.go:456 +0x98
created by testing.RunTests
	/usr/local/go/src/testing/testing.go:561 +0x86d

goroutine 7 [chan receive]:
_/tmp/d20160101-5892-3qo00n.TestStopWithQueueFromForum.func3(0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:584 +0x71
_/tmp/d20160101-5892-3qo00n.(*request).Run(0xc82000a570, 0x0, 0x0, 0x0, 0x0)
	/tmp/d20160101-5892-3qo00n/solution_test.go:37 +0xa5
_/tmp/d20160101-5892-3qo00n.NewRequester.func1(0xc82000a4b0)
	/tmp/d20160101-5892-3qo00n/solution.go:77 +0x254
created by _/tmp/d20160101-5892-3qo00n.NewRequester
	/tmp/d20160101-5892-3qo00n/solution.go:92 +0x16d

goroutine 8 [chan send]:
_/tmp/d20160101-5892-3qo00n.(*RequestHandler).AddRequest(0xc82000a4b0, 0x7fd4fa2b7578, 0xc82000a4e0)
	/tmp/d20160101-5892-3qo00n/solution.go:99 +0x58
created by _/tmp/d20160101-5892-3qo00n.TestStopWithQueueFromForum
	/tmp/d20160101-5892-3qo00n/solution_test.go:612 +0x9c1
exit status 2
FAIL	_/tmp/d20160101-5892-3qo00n	1.006s

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

Ралица обнови решението на 31.12.2015 19:53 (преди над 2 години)

+package main
+
+import (
+ "container/ring"
+ //"sync"
+)
+
+type Request interface {
+ ID() string
+ Run() (result interface{}, err error)
+ Cacheable() bool
+ SetResult(result interface{}, err error)
+}
+
+type Requester interface {
+ AddRequest(request Request)
+ Stop()
+}
+
+const (
+ Working = iota
+ Stopped
+)
+
+type RequestHandler struct {
+ requests chan Request
+ working int
+ sem chan struct{}
+ cache *ring.Ring
+ running map[string]bool
+ // waitgroup sync.WaitGroup
+}
+
+type CacheElement struct {
+ Id string
+ Result interface{}
+ Err error
+}
+
+func NewRequester(cacheSize int, throttleSize int) Requester {
+ requestChannel := make(chan Request)
+ cache := ring.New(cacheSize)
+ running := make(map[string]bool)
+
+ requester := RequestHandler{requests: requestChannel, working: Working, cache: cache, running: running}
+
+ requester.sem = make(chan struct{})
+
+ //requester.waitgroup.Add(throttleSize)
+
+ go func() {
+ for request := range requester.requests {
+
+ ready := false
+
+ requester.cache.Do(func(cacheElement interface{}) {
+ element, _ := cacheElement.(CacheElement)
+
+ if element.Id == request.ID() {
+ request.SetResult(element.Result, element.Err)
+ ready = true
+ }
+ })
+
+ if ready {
+ continue
+ }
+
+ if requester.running[request.ID()] {
+ go func() {
+ requester.requests <- request
+ }()
+ continue
+ }
+
+ requester.running[request.ID()] = true
+ result, err := request.Run()
+ requester.running[request.ID()] = false
+
+ if request.Cacheable() {
+ requester.cache = requester.cache.Next()
+
+ cacheElement := CacheElement{}
+ cacheElement.Id = request.ID()
+ cacheElement.Result, cacheElement.Err = result, err
+
+ requester.cache.Value = cacheElement
+ }
+
+ }
+ requester.sem <- struct{}{}
+ }()
+
+ return &requester
+}
+
+func (r *RequestHandler) AddRequest(request Request) {
+ if r.working == Working {
+ r.requests <- request
+ }
+}
+
+func (r *RequestHandler) Stop() {
+ r.working = Stopped
+ //requester.waitgroup.Wait()
+ close(r.requests)
+ <-r.sem
+}