[#1170] pkg/morph: Invalidate cache on RPC switch
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
6508136204
commit
4ed5b1ceef
5 changed files with 58 additions and 25 deletions
|
@ -39,7 +39,7 @@ import (
|
||||||
// expression (or just declaring a Client variable) is unsafe
|
// expression (or just declaring a Client variable) is unsafe
|
||||||
// and can lead to panic.
|
// and can lead to panic.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
cache
|
cache cache
|
||||||
|
|
||||||
logger *logger.Logger // logging component
|
logger *logger.Logger // logging component
|
||||||
|
|
||||||
|
@ -76,11 +76,50 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type cache struct {
|
type cache struct {
|
||||||
nnsHash util.Uint160
|
m *sync.RWMutex
|
||||||
groupKey *keys.PublicKey
|
|
||||||
|
nnsHash *util.Uint160
|
||||||
|
gKey *keys.PublicKey
|
||||||
txHeights *lru.Cache
|
txHeights *lru.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c cache) nns() *util.Uint160 {
|
||||||
|
c.m.RLock()
|
||||||
|
defer c.m.RUnlock()
|
||||||
|
|
||||||
|
return c.nnsHash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) setNNSHash(nnsHash util.Uint160) {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
c.nnsHash = &nnsHash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c cache) groupKey() *keys.PublicKey {
|
||||||
|
c.m.RLock()
|
||||||
|
defer c.m.RUnlock()
|
||||||
|
|
||||||
|
return c.gKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) setGroupKey(groupKey *keys.PublicKey) {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
c.gKey = groupKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) invalidate() {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
c.nnsHash = nil
|
||||||
|
c.gKey = nil
|
||||||
|
c.txHeights.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrNilClient is returned by functions that expect
|
// ErrNilClient is returned by functions that expect
|
||||||
// a non-nil Client pointer, but received nil.
|
// a non-nil Client pointer, but received nil.
|
||||||
|
|
|
@ -90,7 +90,7 @@ func New(key *keys.PrivateKey, endpoint string, opts ...Option) (*Client, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
cli := &Client{
|
cli := &Client{
|
||||||
cache: initClientCache(),
|
cache: newClientCache(),
|
||||||
logger: cfg.logger,
|
logger: cfg.logger,
|
||||||
acc: wallet.NewAccountFromPrivateKey(key),
|
acc: wallet.NewAccountFromPrivateKey(key),
|
||||||
signer: cfg.signer,
|
signer: cfg.signer,
|
||||||
|
@ -140,9 +140,10 @@ func newWSClient(cfg cfg, endpoint string) (*client.WSClient, error) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initClientCache() cache {
|
func newClientCache() cache {
|
||||||
c, _ := lru.New(100) // returns error only if size is negative
|
c, _ := lru.New(100) // returns error only if size is negative
|
||||||
return cache{
|
return cache{
|
||||||
|
m: &sync.RWMutex{},
|
||||||
txHeights: c,
|
txHeights: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ func (c *Client) switchRPC() bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.cache.invalidate()
|
||||||
c.client = cli
|
c.client = cli
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -83,20 +83,18 @@ func (c *Client) NNSHash() (util.Uint160, error) {
|
||||||
return util.Uint160{}, ErrConnectionLost
|
return util.Uint160{}, ErrConnectionLost
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mtx.RLock()
|
nnsHash := c.cache.nns()
|
||||||
nnsHash := c.nnsHash
|
|
||||||
c.mtx.RUnlock()
|
|
||||||
|
|
||||||
if nnsHash.Equals(util.Uint160{}) {
|
if nnsHash == nil {
|
||||||
cs, err := c.client.GetContractStateByID(nnsContractID)
|
cs, err := c.client.GetContractStateByID(nnsContractID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err)
|
return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err)
|
||||||
}
|
}
|
||||||
c.mtx.Lock()
|
|
||||||
c.nnsHash = cs.Hash
|
c.cache.setNNSHash(cs.Hash)
|
||||||
c.mtx.Unlock()
|
nnsHash = &cs.Hash
|
||||||
}
|
}
|
||||||
return nnsHash, nil
|
return *nnsHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nnsResolveItem(c *client.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
|
func nnsResolveItem(c *client.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
|
||||||
|
@ -202,12 +200,8 @@ func (c *Client) SetGroupSignerScope() error {
|
||||||
|
|
||||||
// contractGroupKey returns public key designating NeoFS contract group.
|
// contractGroupKey returns public key designating NeoFS contract group.
|
||||||
func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
|
func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
|
||||||
c.mtx.RLock()
|
if gKey := c.cache.groupKey(); gKey != nil {
|
||||||
pub := c.groupKey
|
return gKey, nil
|
||||||
c.mtx.RUnlock()
|
|
||||||
|
|
||||||
if pub != nil {
|
|
||||||
return pub, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nnsHash, err := c.NNSHash()
|
nnsHash, err := c.NNSHash()
|
||||||
|
@ -225,13 +219,11 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pub, err = keys.NewPublicKeyFromString(string(bs))
|
pub, err := keys.NewPublicKeyFromString(string(bs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mtx.Lock()
|
c.cache.setGroupKey(pub)
|
||||||
c.groupKey = pub
|
|
||||||
c.mtx.Unlock()
|
|
||||||
return pub, nil
|
return pub, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -873,13 +873,13 @@ func (c *Client) CalculateNonceAndVUB(hash util.Uint256) (nonce uint32, vub uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
|
func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
|
||||||
if rh, ok := c.txHeights.Get(h); ok {
|
if rh, ok := c.cache.txHeights.Get(h); ok {
|
||||||
return rh.(uint32), nil
|
return rh.(uint32), nil
|
||||||
}
|
}
|
||||||
height, err := c.client.GetTransactionHeight(h)
|
height, err := c.client.GetTransactionHeight(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
c.txHeights.Add(h, height)
|
c.cache.txHeights.Add(h, height)
|
||||||
return height, nil
|
return height, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue