package innerring import ( "crypto/ecdsa" "sync" "time" "github.com/nspcc-dev/neofs-node/pkg/innerring/invoke" "github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/pkg/errors" ) type ( innerRingIndexer struct { sync.RWMutex cli *client.Client key *ecdsa.PublicKey timeout time.Duration ind indexes lastAccess time.Time } indexes struct { innerRingIndex, innerRingSize int32 alphabetIndex int32 } ) func newInnerRingIndexer(cli *client.Client, key *ecdsa.PublicKey, to time.Duration) *innerRingIndexer { return &innerRingIndexer{ cli: cli, key: key, timeout: to, } } func (s *innerRingIndexer) update() (ind indexes, err error) { s.RLock() if time.Since(s.lastAccess) < s.timeout { s.RUnlock() return s.ind, nil } s.RUnlock() s.Lock() defer s.Unlock() if time.Since(s.lastAccess) < s.timeout { return s.ind, nil } s.ind.innerRingIndex, s.ind.innerRingSize, err = invoke.InnerRingIndex(s.cli, s.key) if err != nil { return indexes{}, err } s.ind.alphabetIndex, err = invoke.AlphabetIndex(s.cli, s.key) if err != nil { return indexes{}, err } s.lastAccess = time.Now() return s.ind, nil } func (s *innerRingIndexer) InnerRingIndex() (int32, error) { ind, err := s.update() if err != nil { return 0, errors.Wrap(err, "can't update index state") } return ind.innerRingIndex, nil } func (s *innerRingIndexer) InnerRingSize() (int32, error) { ind, err := s.update() if err != nil { return 0, errors.Wrap(err, "can't update index state") } return ind.innerRingSize, nil } func (s *innerRingIndexer) AlphabetIndex() (int32, error) { ind, err := s.update() if err != nil { return 0, errors.Wrap(err, "can't update index state") } return ind.alphabetIndex, nil }