Skip to content

Commit cd4293c

Browse files
author
Jiri Malek
committed
Use in-memory cache to speed up delegation access.
1 parent e1fb50d commit cd4293c

4 files changed

Lines changed: 83 additions & 17 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Package cache implements bridge to fast in-memory object cache.
2+
package cache
3+
4+
import (
5+
"fantom-api-graphql/internal/types"
6+
"github.com/ethereum/go-ethereum/common"
7+
"github.com/ethereum/go-ethereum/common/hexutil"
8+
"strings"
9+
)
10+
11+
// delegationCacheKey generates cache key for the given delegation.
12+
func delegationCacheKey(adr common.Address, valID *hexutil.Big) string {
13+
var key strings.Builder
14+
key.WriteString("dlg")
15+
key.WriteString(adr.String())
16+
key.WriteString("to")
17+
key.WriteString(valID.String())
18+
return key.String()
19+
}
20+
21+
// PullDelegation tries to pull delegation from the given address to the given validator
22+
// from internal in-memory cache.
23+
func (b *MemBridge) PullDelegation(adr common.Address, valID *hexutil.Big) *types.Delegation {
24+
// try to get the account data from the cache
25+
data, err := b.cache.Get(delegationCacheKey(adr, valID))
26+
if err != nil {
27+
return nil
28+
}
29+
30+
// do we have the data?
31+
dlg := new(types.Delegation)
32+
if err := dlg.UnmarshalBSON(data); err != nil {
33+
b.log.Criticalf("can not decode delegation data from in-memory cache; %s", err.Error())
34+
return nil
35+
}
36+
return dlg
37+
}
38+
39+
// PushDelegation stored the given delegation in memory cache.
40+
func (b *MemBridge) PushDelegation(dlg *types.Delegation) {
41+
// no need to store nil
42+
if dlg == nil {
43+
return
44+
}
45+
46+
// encode account
47+
data, err := dlg.MarshalBSON()
48+
if err != nil {
49+
b.log.Criticalf("can not marshal delegation of %s to #%d; %s", dlg.Address.String(), dlg.ToStakerId.ToInt().Uint64(), err.Error())
50+
return
51+
}
52+
53+
// set the data to cache by block number
54+
if err := b.cache.Set(delegationCacheKey(dlg.Address, dlg.ToStakerId), data); err != nil {
55+
b.log.Criticalf("can not cache delegation of %s to #%d; %s", dlg.Address.String(), dlg.ToStakerId.ToInt().Uint64(), err.Error())
56+
}
57+
}

internal/repository/db/delegation.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ func (db *MongoDbBridge) Delegation(addr *common.Address, valID *hexutil.Big) (*
6060
{types.FiDelegationToValidator, valID.String()},
6161
})
6262

63+
// do we have the data?
64+
if sr.Err() != nil {
65+
return nil, sr.Err()
66+
}
67+
6368
// try to decode
6469
var dlg types.Delegation
6570
if err := sr.Decode(&dlg); err != nil {

internal/repository/repository.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,6 @@ type proxy struct {
594594

595595
// service orchestrator reference
596596
orc *orchestrator
597-
598-
// map of delegation balances for updates control
599-
stakedAmounts *StakeAmountMap
600597
}
601598

602599
// newRepository creates new instance of Repository implementation, namely proxy structure.
@@ -621,9 +618,6 @@ func newRepository() Repository {
621618

622619
// keep reference to the SOL compiler
623620
solCompiler: cfg.Compiler.DefaultSolCompilerPath,
624-
625-
// map of delegation amounts
626-
stakedAmounts: NewStakeAmountMap(),
627621
}
628622

629623
// make the service orchestrator and start it's job

internal/repository/sfc_delegation.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (p *proxy) StoreDelegation(dl *types.Delegation) error {
3838
}
3939

4040
// UpdateDelegationBalance updates active balance of the given delegation.
41-
func (p *proxy) UpdateDelegationBalance(addr *common.Address, valID *hexutil.Big, unknown func(*big.Int) error) error {
41+
func (p *proxy) UpdateDelegationBalance(addr *common.Address, valID *hexutil.Big, unknownDelegation func(*big.Int) error) error {
4242
// pull the current value
4343
val, err := p.DelegationAmountStaked(addr, valID)
4444
if err != nil {
@@ -54,8 +54,11 @@ func (p *proxy) UpdateDelegationBalance(addr *common.Address, valID *hexutil.Big
5454

5555
// unknown delegation detected?
5656
if err == db.ErrUnknownDelegation {
57-
return unknown(val)
57+
p.log.Errorf("delegation %s to %d not known yet", addr.String(), valID.ToInt().Uint64())
58+
return unknownDelegation(val)
5859
}
60+
61+
// some other error
5962
p.log.Errorf("delegation %s to %d update failed; %s", addr.String(), valID.ToInt().Uint64(), err.Error())
6063
return err
6164
}
@@ -68,32 +71,39 @@ func (p *proxy) updateDelegationBalance(addr *common.Address, valID *hexutil.Big
6871
return err
6972
}
7073

71-
// do we need to update?
74+
// do we need to update? if the amount did not change, skip the update
7275
if dlg.AmountStaked.ToInt().Cmp(amo) == 0 {
7376
return nil
7477
}
7578

76-
// update the delegation in cache
79+
// update the delegation in DB and memory
7780
dlg.AmountDelegated = (*hexutil.Big)(amo)
78-
79-
// perform the update
80-
return p.db.UpdateDelegationBalance(addr, valID, dlg.AmountDelegated)
81+
err = p.db.UpdateDelegationBalance(addr, valID, dlg.AmountDelegated)
82+
if nil == err {
83+
p.cache.PushDelegation(dlg)
84+
}
85+
return err
8186
}
8287

8388
// Delegation returns a detail of delegation for the given address.
84-
func (p *proxy) Delegation(addr *common.Address, valID *hexutil.Big) (*types.Delegation, error) {
89+
func (p *proxy) Delegation(adr *common.Address, valID *hexutil.Big) (*types.Delegation, error) {
8590
// log what we do
86-
p.log.Debugf("loading delegation of %s to #%d", addr.String(), valID.ToInt().Uint64())
91+
p.log.Debugf("accessing delegation of %s to #%d", adr.String(), valID.ToInt().Uint64())
8792

8893
// try cache first
94+
dlg := p.cache.PullDelegation(*adr, valID)
95+
if dlg != nil {
96+
return dlg, nil
97+
}
8998

90-
// pull from DB instead
91-
dlg, err := p.db.Delegation(addr, valID)
99+
// pull from DB instead; do we actually have it?
100+
dlg, err := p.db.Delegation(adr, valID)
92101
if err != nil {
93102
return nil, err
94103
}
95104

96105
// store to cache for future reference
106+
p.cache.PushDelegation(dlg)
97107
return dlg, nil
98108
}
99109

0 commit comments

Comments
 (0)