Skip to content

Commit 30728a4

Browse files
committed
FEAT: Use templates to store cachable blocks
1 parent 7c8d0e1 commit 30728a4

File tree

3 files changed

+78
-38
lines changed

3 files changed

+78
-38
lines changed

data/interface.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package data
2+
3+
func (h *HyperblockApiResponse) ID() string {
4+
return h.Data.Hyperblock.Hash
5+
}
6+
7+
func (h *HyperblockApiResponse) Hash() string {
8+
return h.Data.Hyperblock.Hash
9+
}
10+
11+
func (h *HyperblockApiResponse) Nonce() uint64 {
12+
return h.Data.Hyperblock.Nonce
13+
}
14+
15+
func (h *BlockApiResponse) ID() string {
16+
return h.Data.Block.Hash
17+
}
18+
19+
func (h *BlockApiResponse) Hash() string {
20+
return h.Data.Block.Hash
21+
}
22+
23+
func (h *BlockApiResponse) Nonce() uint64 {
24+
return h.Data.Block.Nonce
25+
}

process/blockProcessor.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ func NewBlockProcessor(proc Processor) (*BlockProcessor, error) {
5555

5656
// GetBlockByHash will return the block based on its hash
5757
func (bp *BlockProcessor) GetBlockByHash(shardID uint32, hash string, options common.BlockQueryOptions) (*data.BlockApiResponse, error) {
58+
scope := fmt.Sprintf("block:shardID=%d", shardID)
59+
if cached := getObjectFromCache[*data.BlockApiResponse](bp.cache, scope, hash, nil, options); cached != nil {
60+
return *cached, nil
61+
}
62+
5863
observers, err := bp.getObserversOrFullHistoryNodes(shardID)
5964
if err != nil {
6065
return nil, err
@@ -64,23 +69,28 @@ func (bp *BlockProcessor) GetBlockByHash(shardID uint32, hash string, options co
6469

6570
response := data.BlockApiResponse{}
6671
for _, observer := range observers {
67-
6872
_, err := bp.proc.CallGetRestEndPoint(observer.Address, path, &response)
6973
if err != nil {
7074
log.Error("block request", "observer", observer.Address, "error", err.Error())
7175
continue
7276
}
7377

7478
log.Info("block request", "shard id", observer.ShardId, "hash", hash, "observer", observer.Address)
75-
return &response, nil
7679

80+
bp.cacheObject(&response, scope, options)
81+
return &response, nil
7782
}
7883

7984
return nil, WrapObserversError(response.Error)
8085
}
8186

8287
// GetBlockByNonce will return the block based on the nonce
8388
func (bp *BlockProcessor) GetBlockByNonce(shardID uint32, nonce uint64, options common.BlockQueryOptions) (*data.BlockApiResponse, error) {
89+
scope := fmt.Sprintf("block:shardID=%d", shardID)
90+
if cached := getObjectFromCache[*data.BlockApiResponse](bp.cache, scope, "", &nonce, options); cached != nil {
91+
return *cached, nil
92+
}
93+
8494
observers, err := bp.getObserversOrFullHistoryNodes(shardID)
8595
if err != nil {
8696
return nil, err
@@ -90,16 +100,15 @@ func (bp *BlockProcessor) GetBlockByNonce(shardID uint32, nonce uint64, options
90100

91101
response := data.BlockApiResponse{}
92102
for _, observer := range observers {
93-
94103
_, err := bp.proc.CallGetRestEndPoint(observer.Address, path, &response)
95104
if err != nil {
96105
log.Error("block request", "observer", observer.Address, "error", err.Error())
97106
continue
98107
}
99108

100109
log.Info("block request", "shard id", observer.ShardId, "nonce", nonce, "observer", observer.Address)
110+
bp.cacheObject(&response, scope, options)
101111
return &response, nil
102-
103112
}
104113

105114
return nil, WrapObserversError(response.Error)
@@ -116,8 +125,8 @@ func (bp *BlockProcessor) getObserversOrFullHistoryNodes(shardID uint32) ([]*dat
116125

117126
// GetHyperBlockByHash returns the hyperblock by hash
118127
func (bp *BlockProcessor) GetHyperBlockByHash(hash string, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) {
119-
if hyperBlock := bp.getHyperblockFromCache(hash, nil, options); hyperBlock != nil {
120-
return hyperBlock, nil
128+
if cached := getObjectFromCache[*data.HyperblockApiResponse](bp.cache, "hyperblock", hash, nil, options); cached != nil {
129+
return *cached, nil
121130
}
122131

123132
builder := &hyperblockBuilder{}
@@ -143,8 +152,7 @@ func (bp *BlockProcessor) GetHyperBlockByHash(hash string, options common.Hyperb
143152

144153
hyperblock := builder.build(options.NotarizedAtSource)
145154
hyperBlockRsp := data.NewHyperblockApiResponse(hyperblock)
146-
147-
bp.cacheHyperblock(hyperBlockRsp, options)
155+
bp.cacheObject(hyperBlockRsp, "hyperblock", options)
148156

149157
return hyperBlockRsp, nil
150158
}
@@ -191,6 +199,10 @@ func (bp *BlockProcessor) getAlteredAccountsIfNeeded(options common.HyperblockQu
191199

192200
// GetHyperBlockByNonce returns the hyperblock by nonce
193201
func (bp *BlockProcessor) GetHyperBlockByNonce(nonce uint64, options common.HyperblockQueryOptions) (*data.HyperblockApiResponse, error) {
202+
if cached := getObjectFromCache[*data.HyperblockApiResponse](bp.cache, "hyperblock", "", &nonce, options); cached != nil {
203+
return *cached, nil
204+
}
205+
194206
builder := &hyperblockBuilder{}
195207

196208
blockQueryOptions := common.BlockQueryOptions{
@@ -213,7 +225,10 @@ func (bp *BlockProcessor) GetHyperBlockByNonce(nonce uint64, options common.Hype
213225
}
214226

215227
hyperblock := builder.build(options.NotarizedAtSource)
216-
return data.NewHyperblockApiResponse(hyperblock), nil
228+
hyperBlockRsp := data.NewHyperblockApiResponse(hyperblock)
229+
bp.cacheObject(hyperBlockRsp, "hyperblock", options)
230+
231+
return hyperBlockRsp, nil
217232
}
218233

219234
// GetInternalBlockByHash will return the internal block based on its hash

process/blockProcessorCache.go

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,53 @@ package process
33
import (
44
"encoding/json"
55
"fmt"
6-
7-
"github.com/multiversx/mx-chain-proxy-go/common"
8-
"github.com/multiversx/mx-chain-proxy-go/data"
96
)
107

11-
type hyperBlockCacheHandler interface {
12-
cacheHyperblock(resp *data.HyperblockApiResponse, opts common.HyperblockQueryOptions)
13-
getHyperblockFromCache(hash string, nonce *uint64, opts common.HyperblockQueryOptions) *data.HyperblockApiResponse
8+
type cacheableBlock interface {
9+
ID() string
10+
Hash() string
11+
Nonce() uint64
1412
}
1513

16-
func (bp *BlockProcessor) cacheHyperblock(resp *data.HyperblockApiResponse, opts common.HyperblockQueryOptions) {
17-
hashKey := resp.Data.Hyperblock.Hash
18-
optsStr, _ := json.Marshal(opts)
19-
objKey := []byte(hashKey + string(optsStr))
14+
func makeHashCacheKey(scope string, hash string, opts interface{}) []byte {
15+
optBytes, _ := json.Marshal(opts)
16+
return []byte(fmt.Sprintf("%s:hash:%s|opts:%s", scope, hash, string(optBytes)))
17+
}
18+
19+
func makeNonceCacheKey(scope string, nonce uint64, opts interface{}) []byte {
20+
optBytes, _ := json.Marshal(opts)
21+
return []byte(fmt.Sprintf("%s:nonce:%d|opts:%s", scope, nonce, string(optBytes)))
22+
}
23+
24+
func makeObjKey(id string, opts interface{}) []byte {
25+
optBytes, _ := json.Marshal(opts)
26+
return []byte(id + string(optBytes))
27+
}
28+
29+
func (bp *BlockProcessor) cacheObject(obj cacheableBlock, scope string, opts interface{}) {
30+
objKey := makeObjKey(obj.ID(), opts)
2031

2132
// Store object
22-
bp.cache.Put(objKey, resp, 0)
33+
bp.cache.Put(objKey, obj, 0)
2334

2435
// Store nonce + hash lookup keys
25-
bp.cache.Put(getHashCacheKey(resp.Data.Hyperblock.Hash, opts), objKey, 0)
26-
bp.cache.Put(getNonceCacheKey(resp.Data.Hyperblock.Nonce, opts), objKey, 0)
36+
bp.cache.Put(makeHashCacheKey(scope, obj.Hash(), opts), objKey, 0)
37+
bp.cache.Put(makeNonceCacheKey(scope, obj.Nonce(), opts), objKey, 0)
2738
}
2839

29-
func (bp *BlockProcessor) getHyperblockFromCache(hash string, nonce *uint64, opts common.HyperblockQueryOptions) *data.HyperblockApiResponse {
40+
func getObjectFromCache[T cacheableBlock](c TimedCache, scope string, hash string, nonce *uint64, opts interface{}) *T {
3041
var key interface{}
3142
if hash != "" {
32-
key, _ = bp.cache.Get(getHashCacheKey(hash, opts))
43+
key, _ = c.Get(makeHashCacheKey(scope, hash, opts))
3344
} else if nonce != nil {
34-
key, _ = bp.cache.Get(getNonceCacheKey(*nonce, opts))
45+
key, _ = c.Get(makeNonceCacheKey(scope, *nonce, opts))
3546
}
3647

3748
if key != nil {
38-
val, ok := bp.cache.Get(key.([]byte))
49+
val, ok := c.Get(key.([]byte))
3950
if ok {
40-
return val.(*data.HyperblockApiResponse)
51+
return val.(*T)
4152
}
4253
}
43-
4454
return nil
4555
}
46-
47-
func getHashCacheKey(hash string, opts common.HyperblockQueryOptions) []byte {
48-
optBytes, _ := json.Marshal(opts)
49-
return []byte(fmt.Sprintf("hash:%s|opts:%s", hash, string(optBytes)))
50-
}
51-
52-
func getNonceCacheKey(nonce uint64, opts common.HyperblockQueryOptions) []byte {
53-
optBytes, _ := json.Marshal(opts)
54-
return []byte(fmt.Sprintf("nonce:%d|opts:%s", nonce, string(optBytes)))
55-
}

0 commit comments

Comments
 (0)