Commit 269769b3 authored by inphi's avatar inphi

add redis cache impl

parent 18abe83b
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/go-redis/redis/v8"
"github.com/golang/snappy" "github.com/golang/snappy"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
...@@ -13,7 +14,8 @@ type Cache interface { ...@@ -13,7 +14,8 @@ type Cache interface {
Put(ctx context.Context, key string, value string) error Put(ctx context.Context, key string, value string) error
} }
const memoryCacheLimit = 1024 * 1024 // assuming an average RPCRes size of 3 KB
const memoryCacheLimit = 4096
var supportedRPCMethods = map[string]bool{ var supportedRPCMethods = map[string]bool{
"eth_chainId": true, "eth_chainId": true,
...@@ -43,6 +45,35 @@ func (c *cache) Put(ctx context.Context, key string, value string) error { ...@@ -43,6 +45,35 @@ func (c *cache) Put(ctx context.Context, key string, value string) error {
return nil return nil
} }
type redisCache struct {
rdb *redis.Client
}
func newRedisCache(url string) (*redisCache, error) {
opts, err := redis.ParseURL(url)
if err != nil {
return nil, err
}
rdb := redis.NewClient(opts)
if err := rdb.Ping(context.Background()).Err(); err != nil {
return nil, wrapErr(err, "error connecting to redis")
}
return &redisCache{rdb}, nil
}
func (c *redisCache) Get(ctx context.Context, key string) (string, error) {
val, err := c.rdb.Get(ctx, key).Result()
if err != nil {
return "", err
}
return val, nil
}
func (c *redisCache) Put(ctx context.Context, key string, value string) error {
err := c.rdb.Set(ctx, key, value, 0).Err()
return err
}
type RPCCache struct { type RPCCache struct {
cache Cache cache Cache
} }
...@@ -95,13 +126,12 @@ func (c *RPCCache) isCacheable(req *RPCReq) bool { ...@@ -95,13 +126,12 @@ func (c *RPCCache) isCacheable(req *RPCReq) bool {
return false return false
} }
var params []interface{}
if err := json.Unmarshal(req.Params, &params); err != nil {
return false
}
switch req.Method { switch req.Method {
case "eth_getBlockByNumber": case "eth_getBlockByNumber":
var params []interface{}
if err := json.Unmarshal(req.Params, &params); err != nil {
return false
}
if len(params) != 2 { if len(params) != 2 {
return false return false
} }
...@@ -114,6 +144,10 @@ func (c *RPCCache) isCacheable(req *RPCReq) bool { ...@@ -114,6 +144,10 @@ func (c *RPCCache) isCacheable(req *RPCReq) bool {
} }
case "eth_getBlockRange": case "eth_getBlockRange":
var params []interface{}
if err := json.Unmarshal(req.Params, &params); err != nil {
return false
}
if len(params) != 3 { if len(params) != 3 {
return false return false
} }
......
...@@ -156,7 +156,16 @@ func Start(config *Config) error { ...@@ -156,7 +156,16 @@ func Start(config *Config) error {
var rpcCache *RPCCache var rpcCache *RPCCache
if config.Cache != nil && config.Cache.Enabled { if config.Cache != nil && config.Cache.Enabled {
rpcCache = newRPCCache(newMemoryCache()) var cache Cache
if config.Redis != nil {
if cache, err = newRedisCache(config.Redis.URL); err != nil {
return err
}
} else {
log.Warn("redis is not configured, using in-memory cache")
cache = newMemoryCache()
}
rpcCache = newRPCCache(cache)
} }
srv := NewServer( srv := NewServer(
......
...@@ -172,7 +172,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) { ...@@ -172,7 +172,7 @@ func (s *Server) HandleRPC(w http.ResponseWriter, r *http.Request) {
return return
} }
if s.rpcCache != nil { if s.rpcCache != nil && backendRes.Error == nil {
if err = s.rpcCache.PutRPC(ctx, req, backendRes); err != nil { if err = s.rpcCache.PutRPC(ctx, req, backendRes); err != nil {
log.Warn( log.Warn(
"cache put error", "cache put error",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment