frostfs-node/cmd/frostfs-node/frostfsid.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

117 lines
2.9 KiB
Go

package main
import (
"context"
"strings"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid"
"github.com/hashicorp/golang-lru/v2/expirable"
"github.com/nspcc-dev/neo-go/pkg/util"
)
type subjectWithError struct {
subject *client.Subject
err error
}
type subjectExtWithError struct {
subject *client.SubjectExtended
err error
}
type morphFrostfsIDCache struct {
subjProvider frostfsidcore.SubjectProvider
subjCache *expirable.LRU[util.Uint160, subjectWithError]
subjExtCache *expirable.LRU[util.Uint160, subjectExtWithError]
metrics cacheMetrics
}
func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int, ttl time.Duration, metrics cacheMetrics) frostfsidcore.SubjectProvider {
return &morphFrostfsIDCache{
subjProvider: subjProvider,
subjCache: expirable.NewLRU(size, func(util.Uint160, subjectWithError) {}, ttl),
subjExtCache: expirable.NewLRU(size, func(util.Uint160, subjectExtWithError) {}, ttl),
metrics: metrics,
}
}
func (m *morphFrostfsIDCache) GetSubject(ctx context.Context, addr util.Uint160) (*client.Subject, error) {
hit := false
startedAt := time.Now()
defer func() {
m.metrics.AddMethodDuration("GetSubject", time.Since(startedAt), hit)
}()
result, found := m.subjCache.Get(addr)
if found {
hit = true
return result.subject, result.err
}
subj, err := m.subjProvider.GetSubject(ctx, addr)
if err != nil {
if m.isCacheableError(err) {
m.subjCache.Add(addr, subjectWithError{
err: err,
})
}
return nil, err
}
m.subjCache.Add(addr, subjectWithError{subject: subj})
return subj, nil
}
func (m *morphFrostfsIDCache) GetSubjectExtended(ctx context.Context, addr util.Uint160) (*client.SubjectExtended, error) {
hit := false
startedAt := time.Now()
defer func() {
m.metrics.AddMethodDuration("GetSubjectExtended", time.Since(startedAt), hit)
}()
result, found := m.subjExtCache.Get(addr)
if found {
hit = true
return result.subject, result.err
}
subjExt, err := m.subjProvider.GetSubjectExtended(ctx, addr)
if err != nil {
if m.isCacheableError(err) {
m.subjExtCache.Add(addr, subjectExtWithError{
err: err,
})
m.subjCache.Add(addr, subjectWithError{
err: err,
})
}
return nil, err
}
m.subjExtCache.Add(addr, subjectExtWithError{subject: subjExt})
m.subjCache.Add(addr, subjectWithError{subject: subjectFromSubjectExtended(subjExt)})
return subjExt, nil
}
func (m *morphFrostfsIDCache) isCacheableError(err error) bool {
return strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage)
}
func subjectFromSubjectExtended(subjExt *client.SubjectExtended) *client.Subject {
return &client.Subject{
PrimaryKey: subjExt.PrimaryKey,
AdditionalKeys: subjExt.AdditionalKeys,
Namespace: subjExt.Namespace,
Name: subjExt.Name,
KV: subjExt.KV,
}
}