diff --git a/go/Makefile b/go/Makefile index f57a88f..e708548 100644 --- a/go/Makefile +++ b/go/Makefile @@ -2,7 +2,7 @@ BINARIES=exsrv excli all: $(BINARIES) -exsrv: redrpc/*.go commands/exsrv/*.go +exsrv: show-todos redrpc/*.go commands/exsrv/*.go ./scripts/go build -o "$@" github.com/Codility/redis-rpc/go/commands/exsrv excli: redrpc/*.go commands/excli/*.go @@ -13,7 +13,7 @@ clean: rm -rf $(BINARIES) .gopath .PHONY: test -test: goimports govet +test: show-todos goimports govet ./scripts/go test -v github.com/Codility/redis-rpc/go/redrpc .PHONY: govet @@ -32,3 +32,10 @@ goimports: exit 1; \ fi @echo "goimports passed" + +.PHONY: show-todos +show-todos: + @echo "---------- TODOs ----------" + @grep --line-number '// TODO' `find . -name \*.go | grep -v '\(/vendor/\|/.gopath/\)'` \ + | LC_ALL=C perl -ple 's|^([^:]+:[^:]+:)[^/]*|sprintf("%-40s", $$1)|e' + @echo diff --git a/go/redrpc/server.go b/go/redrpc/server.go index e12aff3..06cf44a 100644 --- a/go/redrpc/server.go +++ b/go/redrpc/server.go @@ -41,7 +41,8 @@ type Server struct { queues []string queueMap map[string]string - closing int64 + closing int64 + iterations int } type RequestImpl struct { @@ -98,7 +99,9 @@ func (s *Server) Run() { } func (s *Server) RunOnce() bool { - res, err := s.red.BLPop(time.Second, s.queues...) + res, err := s.red.BLPop(time.Second, rotated(s.queues, s.iterations)...) + s.iterations += 1 + if err != nil && err != redis.Nil { log.Print("Error in BLPOP: ", err) return false @@ -210,3 +213,11 @@ func (s *Server) sendResponse(func_name string, req *RequestImpl, res interface{ func (s *Server) timestamp() string { return s.opts.TimeSource().Format(time.RFC3339) } + +func rotated(s []string, i int) []string { + if len(s) == 0 { + return s + } + i = i % len(s) + return append(s[i:], s[:i]...) +} diff --git a/go/redrpc/server_test.go b/go/redrpc/server_test.go index 5ae6e33..6c43f16 100644 --- a/go/redrpc/server_test.go +++ b/go/redrpc/server_test.go @@ -130,3 +130,28 @@ func TestPropagatePanic(t *testing.T) { assert.Equal(t, result, []string{"redis_rpc:test:result:call-id", `{"ts":"2018-01-01T00:00:00Z","err":"oh no"}`}) assert.Equal(t, resultTTL, 10*time.Second) } + +func TestServerRotatesQueues(t *testing.T) { + blpopCalls := [][]string{} + + red := &TestDbAdapter{ + blpopMock: func(timeout time.Duration, keys ...string) ([]string, error) { + blpopCalls = append(blpopCalls, keys) + return nil, nil + }, + } + srv := NewServerWithAdapter(red, nil, map[string]Handler{ + "a": HandlerFunc(func(req Request) (interface{}, error) { return nil, nil }), + "b": HandlerFunc(func(req Request) (interface{}, error) { return nil, nil }), + "c": HandlerFunc(func(req Request) (interface{}, error) { return nil, nil }), + }) + assert.True(t, srv.RunOnce()) + assert.True(t, srv.RunOnce()) + assert.True(t, srv.RunOnce()) + + assert.Equal(t, blpopCalls, [][]string{ + []string{"redis_rpc:a:calls", "redis_rpc:b:calls", "redis_rpc:c:calls"}, + []string{"redis_rpc:b:calls", "redis_rpc:c:calls", "redis_rpc:a:calls"}, + []string{"redis_rpc:c:calls", "redis_rpc:a:calls", "redis_rpc:b:calls"}, + }) +}