Skip to content

Commit 52bbb91

Browse files
committed
fix - redis cache support
1 parent 67bc012 commit 52bbb91

File tree

2 files changed

+79
-35
lines changed

2 files changed

+79
-35
lines changed

cache/redis_cache.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package cache
22

33
import (
44
"context"
5+
"encoding/json"
6+
"reflect"
57

68
"github.com/go-redis/redis/v8"
79
)
@@ -34,15 +36,40 @@ func NewRedisCache() *RedisCache {
3436
}
3537

3638
func (c *RedisCache) Set(key string, value interface{}) error {
37-
c.cache.Set(ctx, key, value, 0)
39+
valueType := reflect.TypeOf(value)
40+
switch valueType.Kind() {
41+
case reflect.Map:
42+
br, _ := json.Marshal(value)
43+
c.cache.Set(ctx, key, string(br), 0)
44+
c.cache.Set(ctx, key+"_type", "reflect.Map", 0)
45+
case reflect.Slice:
46+
br, _ := json.Marshal(value)
47+
c.cache.Set(ctx, key, string(br), 0)
48+
c.cache.Set(ctx, key+"_type", "reflect.Slice", 0)
49+
default:
50+
c.cache.Set(ctx, key, value, 0)
51+
}
3852
return nil
3953
}
4054

4155
func (c *RedisCache) Get(key string) (interface{}, error) {
56+
typeValue, _ := c.cache.Get(ctx, key+"_type").Result()
4257
val, err := c.cache.Get(ctx, key).Result()
4358
if err != nil {
4459
return nil, err
4560
}
61+
62+
switch typeValue {
63+
case "reflect.Map":
64+
var m map[string]interface{}
65+
json.Unmarshal([]byte(val), &m)
66+
return m, nil
67+
case "reflect.Slice":
68+
var s []interface{}
69+
json.Unmarshal([]byte(val), &s)
70+
return s, nil
71+
}
72+
4673
return val, nil
4774
}
4875

handlers/cached.go

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ import (
1010
"graphql_cache/utils/ast_utils"
1111
"graphql_cache/utils/test_endpoints"
1212
"strings"
13+
"time"
1314

1415
"github.com/vektah/gqlparser/ast"
1516
)
1617

17-
var cacheStore = cache.NewInMemoryCache()
18-
var recordCacheStore = cache.NewInMemoryCache()
19-
var queryCacheStore = cache.NewInMemoryCache()
18+
var cacheStore = cache.NewRedisCache()
19+
var recordCacheStore = cache.NewRedisCache()
20+
var queryCacheStore = cache.NewRedisCache()
2021

2122
func ProxyToCachedAPI() []byte {
23+
start := time.Now()
2224
copiedRequestBody := test_endpoints.REQUEST_BODY
2325
// Parse the query
2426

@@ -29,10 +31,13 @@ func ProxyToCachedAPI() []byte {
2931
return nil
3032
}
3133

34+
fmt.Println("time taken to generate AST ", time.Since(start))
35+
3236
cachedResponse, err := ParseASTBuildResponse(astQuery, copiedRequestBody)
3337
if err == nil && cachedResponse != nil {
3438
fmt.Println("serving response from cache...")
3539
br, _ := json.Marshal(cachedResponse)
40+
fmt.Println("time taken to serve response from cache ", time.Since(start))
3641
return RemoveTypenameFromResponse(br)
3742
}
3843

@@ -42,6 +47,8 @@ func ProxyToCachedAPI() []byte {
4247
return nil
4348
}
4449

50+
fmt.Println("time taken to transform body ", time.Since(start))
51+
4552
copiedRequestBody["query"] = transformedBody
4653

4754
response := test_endpoints.GetSampleAPIResponse(copiedRequestBody)
@@ -51,12 +58,16 @@ func ProxyToCachedAPI() []byte {
5158
fmt.Println("Error unmarshalling response:", err)
5259
}
5360

61+
fmt.Println("time taken to get response from API ", time.Since(start))
62+
5463
astWithTypes, err := ast_utils.GetASTFromQuery(transformedBody)
5564
if err != nil {
5665
fmt.Println("Error parsing query:", err)
5766
return nil
5867
}
5968

69+
fmt.Println("time taken to generate AST with types ", time.Since(start))
70+
6071
reqVariables := copiedRequestBody["variables"]
6172
variables := make(map[string]interface{})
6273
if reqVariables != nil {
@@ -73,13 +84,17 @@ func ProxyToCachedAPI() []byte {
7384
}
7485
}
7586

87+
fmt.Println("time taken to build response key ", time.Since(start))
88+
7689
// go through the response. Every object that has a __typename field, and an id field cache it in the format of typename:id
7790
// for example, if the response has an object with __typename: "Organisation" and id: "1234", cache it as Organisation:1234
7891
// if the object has a nested object with __typename: "User" and id: "5678", cache
7992
// it as User:5678
8093

8194
CacheResponse("data", responseMap, nil)
8295

96+
fmt.Println("time taken to cache response ", time.Since(start))
97+
8398
cacheStore.Debug("cacheStore")
8499
recordCacheStore.Debug("recordCacheStore")
85100
queryCacheStore.Debug("queryCacheStore")
@@ -93,6 +108,7 @@ func ProxyToCachedAPI() []byte {
93108
// queryCacheState, _ := queryCacheStore.JSON()
94109
// fmt.Println(string(queryCacheState))
95110

111+
fmt.Println("time taken to finish completely ", time.Since(start))
96112
return RemoveTypenameFromResponse(response)
97113
}
98114

@@ -230,48 +246,49 @@ func TraverseResponseFromKey(response interface{}) (interface{}, error) {
230246
}
231247
return TraverseResponseFromKey(response)
232248
}
233-
}
234-
responseMap := response.(map[string]interface{})
235-
for key, value := range responseMap {
236-
if val, ok := value.(string); ok { // handle other data types, arrays and objects
237-
if strings.HasPrefix(val, "gql:") {
238-
nestedResponse, err := TraverseResponseFromKey(val)
239-
if err != nil {
240-
fmt.Println("Error traversing nested response from key:", val, " ", err)
241-
return nil, err
249+
} else if responseMap, ok := response.(map[string]interface{}); ok {
250+
for key, value := range responseMap {
251+
if val, ok := value.(string); ok { // handle other data types, arrays and objects
252+
if strings.HasPrefix(val, "gql:") {
253+
nestedResponse, err := TraverseResponseFromKey(val)
254+
if err != nil {
255+
fmt.Println("Error traversing nested response from key:", val, " ", err)
256+
return nil, err
257+
}
258+
responseMap[key] = nestedResponse
242259
}
243-
responseMap[key] = nestedResponse
244-
}
245-
} else if val, ok := value.(map[string]interface{}); ok {
246-
for k, v := range val {
247-
if v, ok := v.(string); ok {
248-
if strings.HasPrefix(v, "gql:") {
249-
nestedResponse, err := TraverseResponseFromKey(v)
250-
if err != nil {
251-
fmt.Println("Error traversing nested response from key:", v, " ", err)
252-
return nil, err
260+
} else if val, ok := value.(map[string]interface{}); ok {
261+
for k, v := range val {
262+
if v, ok := v.(string); ok {
263+
if strings.HasPrefix(v, "gql:") {
264+
nestedResponse, err := TraverseResponseFromKey(v)
265+
if err != nil {
266+
fmt.Println("Error traversing nested response from key:", v, " ", err)
267+
return nil, err
268+
}
269+
val[k] = nestedResponse
253270
}
254-
val[k] = nestedResponse
255271
}
256272
}
257-
}
258-
} else if val, ok := value.([]interface{}); ok {
259-
for i, v := range val {
260-
if v, ok := v.(string); ok {
261-
if strings.HasPrefix(v, "gql:") {
262-
nestedResponse, err := TraverseResponseFromKey(v)
263-
if err != nil {
264-
fmt.Println("Error traversing nested response from key:", v, " ", err)
265-
return nil, err
273+
} else if val, ok := value.([]interface{}); ok {
274+
for i, v := range val {
275+
if v, ok := v.(string); ok {
276+
if strings.HasPrefix(v, "gql:") {
277+
nestedResponse, err := TraverseResponseFromKey(v)
278+
if err != nil {
279+
fmt.Println("Error traversing nested response from key:", v, " ", err)
280+
return nil, err
281+
}
282+
val[i] = nestedResponse
266283
}
267-
val[i] = nestedResponse
268284
}
269285
}
270286
}
271287
}
288+
return responseMap, nil
272289
}
273290

274-
return responseMap, nil
291+
return nil, nil
275292
}
276293

277294
func CacheObject(field string, object map[string]interface{}, parent map[string]interface{}) string {

0 commit comments

Comments
 (0)