frostfs-node/pkg/innerring/indexer.go
Alexander Chuprov 9b113c3156
Some checks failed
DCO action / DCO (pull_request) Successful in 59s
Vulncheck / Vulncheck (pull_request) Successful in 1m4s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m55s
Build / Build Components (pull_request) Successful in 2m4s
Tests and linters / Staticcheck (pull_request) Successful in 2m38s
Tests and linters / Lint (pull_request) Successful in 3m16s
Tests and linters / Run gofumpt (pull_request) Successful in 3m54s
Tests and linters / Tests (pull_request) Successful in 4m12s
Tests and linters / gopls check (pull_request) Successful in 4m31s
Tests and linters / Tests with -race (pull_request) Successful in 4m38s
OCI image / Build container images (push) Failing after 18s
Vulncheck / Vulncheck (push) Successful in 1m2s
Pre-commit hooks / Pre-commit (push) Successful in 1m39s
Build / Build Components (push) Successful in 1m45s
Tests and linters / Staticcheck (push) Successful in 2m18s
Tests and linters / Run gofumpt (push) Successful in 2m46s
Tests and linters / Lint (push) Successful in 3m5s
Tests and linters / Tests with -race (push) Successful in 3m23s
Tests and linters / Tests (push) Successful in 3m52s
Tests and linters / gopls check (push) Successful in 4m18s
[#1613] morph: Add tracing for morph queries to neo-go
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2025-02-05 16:38:20 +03:00

121 lines
2.4 KiB
Go

package innerring
import (
"context"
"fmt"
"sync"
"time"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
)
type (
irFetcher interface {
InnerRingKeys(ctx context.Context) (keys.PublicKeys, error)
}
committeeFetcher interface {
Committee() (keys.PublicKeys, error)
}
innerRingIndexer struct {
sync.RWMutex
irFetcher irFetcher
commFetcher committeeFetcher
key *keys.PublicKey
timeout time.Duration
ind indexes
lastAccess time.Time
}
indexes struct {
innerRingIndex, innerRingSize int32
alphabetIndex int32
}
)
func newInnerRingIndexer(comf committeeFetcher, irf irFetcher, key *keys.PublicKey, to time.Duration) *innerRingIndexer {
return &innerRingIndexer{
irFetcher: irf,
commFetcher: comf,
key: key,
timeout: to,
}
}
func (s *innerRingIndexer) update(ctx context.Context) (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
}
innerRing, err := s.irFetcher.InnerRingKeys(ctx)
if err != nil {
return indexes{}, err
}
s.ind.innerRingIndex = keyPosition(s.key, innerRing)
s.ind.innerRingSize = int32(len(innerRing))
alphabet, err := s.commFetcher.Committee()
if err != nil {
return indexes{}, err
}
s.ind.alphabetIndex = keyPosition(s.key, alphabet)
s.lastAccess = time.Now()
return s.ind, nil
}
func (s *innerRingIndexer) InnerRingIndex(ctx context.Context) (int32, error) {
ind, err := s.update(ctx)
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.innerRingIndex, nil
}
func (s *innerRingIndexer) InnerRingSize(ctx context.Context) (int32, error) {
ind, err := s.update(ctx)
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.innerRingSize, nil
}
func (s *innerRingIndexer) AlphabetIndex(ctx context.Context) (int32, error) {
ind, err := s.update(ctx)
if err != nil {
return 0, fmt.Errorf("can't update index state: %w", err)
}
return ind.alphabetIndex, nil
}
// keyPosition returns "-1" if key is not found in the list, otherwise returns
// index of the key.
func keyPosition(key *keys.PublicKey, list keys.PublicKeys) int32 {
for i := range list {
if key.Equal(list[i]) {
return int32(i)
}
}
return -1
}