[#16] frostfsid: Fix client invocation
All checks were successful
/ DCO (pull_request) Successful in 50s
/ Vulncheck (pull_request) Successful in 1m4s
/ Builds (1.21) (pull_request) Successful in 1m11s
/ Builds (1.22) (pull_request) Successful in 1m9s
/ Lint (pull_request) Successful in 2m7s
/ Tests (1.21) (pull_request) Successful in 1m16s
/ Tests (1.22) (pull_request) Successful in 1m14s

Previously we cannot switch to new client after connection was lost

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2024-07-30 17:51:40 +03:00
parent aaa652de67
commit b3677cefbb

View file

@ -2,21 +2,19 @@ package contract
import (
"errors"
"sync"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
morphclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
"git.frostfs.info/TrueCloudLab/frostfs-s3-lifecycler/internal/morph"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
type FrostFSID struct {
morphClient *morph.Client
contractHash util.Uint160
mu sync.RWMutex
cli *client.Client
}
type FrostFSIDConfig struct {
@ -32,7 +30,6 @@ func NewFrostFSID(cfg FrostFSIDConfig) *FrostFSID {
ffsid := &FrostFSID{
morphClient: cfg.Client,
contractHash: cfg.ContractHash,
cli: client.NewSimple(cfg.Client.Client().GetActor(), cfg.ContractHash),
}
return ffsid
@ -40,10 +37,21 @@ func NewFrostFSID(cfg FrostFSIDConfig) *FrostFSID {
func (f *FrostFSID) Users() ([]util.Uint160, error) {
var res []util.Uint160
err := f.requestWithRetryOnConnectionLost(func(c *client.Client) error {
var inErr error
res, inErr = c.ListSubjects()
return inErr
err := f.requestWithRetryOnConnectionLost(func() error {
return f.morphClient.Client().TestInvokeIterator(func(item stackitem.Item) error {
raw, err := item.TryBytes()
if err != nil {
return fmt.Errorf("trye item bytes: %w", err)
}
userHash, err := util.Uint160DecodeBytesBE(raw)
if err != nil {
return fmt.Errorf("decode user hash: %w", err)
}
res = append(res, userHash)
return nil
}, 100, f.contractHash, "listSubjects")
})
return res, err
@ -51,10 +59,26 @@ func (f *FrostFSID) Users() ([]util.Uint160, error) {
func (f *FrostFSID) UserKey(hash util.Uint160) (*keys.PublicKey, error) {
var res *client.Subject
err := f.requestWithRetryOnConnectionLost(func(c *client.Client) error {
var inErr error
res, inErr = c.GetSubject(hash)
return inErr
err := f.requestWithRetryOnConnectionLost(func() error {
resItems, err := f.morphClient.Client().TestInvoke(f.contractHash, "getSubject", hash)
if err != nil {
return fmt.Errorf("invoke getSubject: %w", err)
}
if len(resItems) != 1 {
return fmt.Errorf("length getSubject stack unexpected: %d", len(resItems))
}
arr, ok := resItems[0].Value().([]stackitem.Item)
if !ok {
return errors.New("not an array")
}
if res, err = client.ParseSubject(arr); err != nil {
return fmt.Errorf("parse subject: %w", err)
}
return nil
})
if err != nil {
return nil, err
@ -63,8 +87,8 @@ func (f *FrostFSID) UserKey(hash util.Uint160) (*keys.PublicKey, error) {
return res.PrimaryKey, nil
}
func (f *FrostFSID) requestWithRetryOnConnectionLost(fn func(c *client.Client) error) error {
err := fn(f.client())
func (f *FrostFSID) requestWithRetryOnConnectionLost(fn func() error) error {
err := fn()
if err == nil {
return nil
}
@ -73,20 +97,5 @@ func (f *FrostFSID) requestWithRetryOnConnectionLost(fn func(c *client.Client) e
return err
}
f.initNewClient()
return fn(f.client())
}
func (f *FrostFSID) initNewClient() {
f.mu.Lock()
f.cli = client.NewSimple(f.morphClient.Client().GetActor(), f.contractHash)
f.mu.Unlock()
}
func (f *FrostFSID) client() *client.Client {
f.mu.RLock()
defer f.mu.RUnlock()
return f.cli
return fn()
}