diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go index 9039915f5..3cca09105 100644 --- a/cmd/frostfs-node/frostfsid.go +++ b/cmd/frostfs-node/frostfsid.go @@ -1,6 +1,7 @@ package main import ( + "strings" "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" @@ -9,10 +10,22 @@ import ( "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, *client.Subject] + subjCache *expirable.LRU[util.Uint160, subjectWithError] + + subjExtCache *expirable.LRU[util.Uint160, subjectExtWithError] metrics cacheMetrics } @@ -21,7 +34,9 @@ func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int return &morphFrostfsIDCache{ subjProvider: subjProvider, - subjCache: expirable.NewLRU(size, func(util.Uint160, *client.Subject) {}, ttl), + subjCache: expirable.NewLRU(size, func(util.Uint160, subjectWithError) {}, ttl), + + subjExtCache: expirable.NewLRU(size, func(util.Uint160, subjectExtWithError) {}, ttl), metrics: metrics, } @@ -37,16 +52,21 @@ func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, er result, found := m.subjCache.Get(addr) if found { hit = true - return result, nil + return result.subject, result.err } - result, err := m.subjProvider.GetSubject(addr) + subj, err := m.subjProvider.GetSubject(addr) if err != nil { + if m.isCacheableError(err) { + m.subjCache.Add(addr, subjectWithError{ + err: err, + }) + } return nil, err } - m.subjCache.Add(addr, result) - return result, nil + m.subjCache.Add(addr, subjectWithError{subject: subj}) + return subj, nil } func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { @@ -59,21 +79,32 @@ func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.Sub result, found := m.subjExtCache.Get(addr) if found { hit = true - return result, nil + return result.subject, result.err } - var err error - subjExt, err = m.subjProvider.GetSubjectExtended(addr) + subjExt, err := m.subjProvider.GetSubjectExtended(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, subjExt) - m.subjCache.Add(addr, subjectFromSubjectExtended(subjExt)) + 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,