Skip to content

Commit 6912b53

Browse files
authored
Merge pull request #12 from qa-dev/cache
add cache
2 parents d6b0955 + 8b89a9d commit 6912b53

File tree

5 files changed

+130
-9
lines changed

5 files changed

+130
-9
lines changed

handlers/useSession.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
)
1212

1313
type UseSession struct {
14-
Pool *pool.Pool
14+
Pool *pool.Pool
15+
Cache *pool.Cache
1516
}
1617

1718
func (h *UseSession) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
@@ -24,12 +25,17 @@ func (h *UseSession) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
2425
return
2526
}
2627
sessionID := re.FindStringSubmatch(r.URL.Path)[1]
27-
targetNode, err := h.Pool.GetNodeBySessionID(sessionID)
28-
if err != nil {
29-
errorMessage := "session " + sessionID + " not found in node pool: " + err.Error()
30-
log.Infof(errorMessage)
31-
http.Error(rw, errorMessage, http.StatusNotFound)
32-
return
28+
targetNode, ok := h.Cache.Get(sessionID)
29+
var err error
30+
if !ok {
31+
targetNode, err = h.Pool.GetNodeBySessionID(sessionID)
32+
if err != nil {
33+
errorMessage := "session " + sessionID + " not found in node pool: " + err.Error()
34+
log.Infof(errorMessage)
35+
http.Error(rw, errorMessage, http.StatusNotFound)
36+
return
37+
}
38+
h.Cache.Set(sessionID, targetNode)
3339
}
3440

3541
proxy := httputil.NewSingleHostReverseProxy(&url.URL{

main.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,22 @@ func main() {
9494
}
9595
}()
9696

97+
cache := pool.NewCache(time.Minute * 10) // todo: move to config
98+
99+
go func() {
100+
for {
101+
cache.CleanUp()
102+
time.Sleep(time.Minute) // todo: move to config
103+
}
104+
}()
105+
97106
m := middleware.NewLogMiddleware(statsdClient)
98107
http.Handle("/wd/hub/session", m.Log(&handlers.CreateSession{Pool: poolInstance, ClientFactory: clientFactory})) //selenium
99108
http.Handle("/session", m.Log(&handlers.CreateSession{Pool: poolInstance, ClientFactory: clientFactory})) //wda
100109
http.Handle("/grid/register", m.Log(&handlers.RegisterNode{Pool: poolInstance}))
101110
http.Handle("/grid/api/proxy", &handlers.APIProxy{Pool: poolInstance})
102111
http.HandleFunc("/_info", heartbeat)
103-
http.Handle("/", m.Log(&handlers.UseSession{Pool: poolInstance}))
112+
http.Handle("/", m.Log(&handlers.UseSession{Pool: poolInstance, Cache: cache}))
104113

105114
server := &http.Server{Addr: fmt.Sprintf(":%v", cfg.Grid.Port)}
106115
serverError := make(chan error)

pool/cache.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package pool
2+
3+
import (
4+
"sync"
5+
"time"
6+
)
7+
8+
// Cache no thread safe
9+
type Cache struct {
10+
storage map[string]*cacheEntry
11+
expirationTime time.Duration
12+
sync.RWMutex
13+
}
14+
15+
type cacheEntry struct {
16+
node *Node
17+
created time.Time
18+
}
19+
20+
func NewCache(expirationTime time.Duration) *Cache {
21+
return &Cache{
22+
storage: make(map[string]*cacheEntry),
23+
expirationTime: expirationTime,
24+
}
25+
}
26+
27+
func (c *Cache) Set(key string, node *Node) {
28+
c.Lock()
29+
c.storage[key] = &cacheEntry{
30+
node: node,
31+
created: time.Now(),
32+
}
33+
c.Unlock()
34+
}
35+
36+
func (c *Cache) Get(key string) (node *Node, ok bool) {
37+
c.RLock()
38+
entry, ok := c.storage[key]
39+
if !ok {
40+
c.RUnlock()
41+
return nil, false
42+
}
43+
c.RUnlock()
44+
return entry.node, true
45+
}
46+
47+
func (c *Cache) CleanUp() {
48+
c.Lock()
49+
for i, _ := range c.storage {
50+
if time.Since(c.storage[i].created) > c.expirationTime {
51+
delete(c.storage, i)
52+
}
53+
}
54+
c.Unlock()
55+
}

pool/cache_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package pool
2+
3+
import (
4+
"testing"
5+
"github.com/stretchr/testify/assert"
6+
"time"
7+
)
8+
9+
func TestNewCache(t *testing.T) {
10+
c := NewCache(time.Second)
11+
assert.NotNil(t, c)
12+
}
13+
14+
func TestCache_Set_ReturnsNode(t *testing.T) {
15+
c := NewCache(time.Second)
16+
key := "1"
17+
node := new(Node)
18+
c.Set(key, node)
19+
assert.Equal(t, node, c.storage[key].node)
20+
}
21+
22+
func TestCache_Get_NodeExists_ReturnsNodeTrue(t *testing.T) {
23+
c := NewCache(time.Second)
24+
key := "1"
25+
nodeExp := new(Node)
26+
c.storage[key] = &cacheEntry{node: nodeExp, created: time.Now()}
27+
node, ok := c.Get(key)
28+
assert.Equal(t, nodeExp, node)
29+
assert.True(t, ok)
30+
}
31+
32+
func TestCache_Get_NodeNotExists_ReturnsNilFalse(t *testing.T) {
33+
c := NewCache(time.Second)
34+
key := "1"
35+
node, ok := c.Get(key)
36+
assert.Nil(t, node)
37+
assert.False(t, ok)
38+
}
39+
40+
func TestCache_CleanUp_ExpiredPart_RemoveExpired(t *testing.T) {
41+
c := NewCache(time.Minute)
42+
nodeExp := new(Node)
43+
c.storage["1"] = &cacheEntry{node: nodeExp, created: time.Now().Add(-time.Hour)}
44+
c.storage["2"] = &cacheEntry{node: nodeExp, created: time.Now().Add(-time.Hour)}
45+
c.storage["3"] = &cacheEntry{node: nodeExp, created: time.Now().Add(time.Hour)}
46+
c.storage["4"] = &cacheEntry{node: nodeExp, created: time.Now().Add(time.Hour)}
47+
c.CleanUp()
48+
assert.Len(t, c.storage, 2)
49+
}

testing/webdriver-node-mock/handlers.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"time"
1414
)
1515

16+
var constResponse = RandStringRunes(10000)
17+
1618
// status return current status
1719
func status(rw http.ResponseWriter, r *http.Request) {
1820
sessions := &jsonwire.Message{}
@@ -108,7 +110,7 @@ func useSession(rw http.ResponseWriter, r *http.Request) {
108110
case parsedUrl[2] == "" && r.Method == http.MethodDelete: // session closed by client
109111
currentSessionID = ""
110112
default:
111-
responseMessage.Value = RandStringRunes(10000)
113+
responseMessage.Value = constResponse
112114
}
113115
err := json.NewEncoder(rw).Encode(responseMessage)
114116
if err != nil {

0 commit comments

Comments
 (0)