forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 0
/
methods.go
92 lines (79 loc) · 2.05 KB
/
methods.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package proxyd
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"strings"
"sync"
"github.com/ethereum/go-ethereum/log"
)
type RPCMethodHandler interface {
GetRPCMethod(context.Context, *RPCReq) (*RPCRes, error)
PutRPCMethod(context.Context, *RPCReq, *RPCRes) error
}
type StaticMethodHandler struct {
cache Cache
m sync.RWMutex
filterGet func(*RPCReq) bool
filterPut func(*RPCReq, *RPCRes) bool
}
func (e *StaticMethodHandler) key(req *RPCReq) string {
// signature is the hashed json.RawMessage param contents
h := sha256.New()
h.Write(req.Params)
signature := fmt.Sprintf("%x", h.Sum(nil))
return strings.Join([]string{"cache", req.Method, signature}, ":")
}
func (e *StaticMethodHandler) GetRPCMethod(ctx context.Context, req *RPCReq) (*RPCRes, error) {
if e.cache == nil {
return nil, nil
}
if e.filterGet != nil && !e.filterGet(req) {
return nil, nil
}
e.m.RLock()
defer e.m.RUnlock()
key := e.key(req)
val, err := e.cache.Get(ctx, key)
if err != nil {
log.Error("error reading from cache", "key", key, "method", req.Method, "err", err)
return nil, err
}
if val == "" {
return nil, nil
}
var result interface{}
if err := json.Unmarshal([]byte(val), &result); err != nil {
log.Error("error unmarshalling value from cache", "key", key, "method", req.Method, "err", err)
return nil, err
}
return &RPCRes{
JSONRPC: req.JSONRPC,
Result: result,
ID: req.ID,
}, nil
}
func (e *StaticMethodHandler) PutRPCMethod(ctx context.Context, req *RPCReq, res *RPCRes) error {
if e.cache == nil {
return nil
}
// if there is a filter on get, we don't want to cache it because its irretrievable
if e.filterGet != nil && !e.filterGet(req) {
return nil
}
// response filter
if e.filterPut != nil && !e.filterPut(req, res) {
return nil
}
e.m.Lock()
defer e.m.Unlock()
key := e.key(req)
value := mustMarshalJSON(res.Result)
err := e.cache.Put(ctx, key, string(value))
if err != nil {
log.Error("error putting into cache", "key", key, "method", req.Method, "err", err)
return err
}
return nil
}