diff --git a/cmd/neofs-node/cache.go b/cmd/neofs-node/cache.go index c06c527de..3b1be2ce2 100644 --- a/cmd/neofs-node/cache.go +++ b/cmd/neofs-node/cache.go @@ -319,3 +319,39 @@ func (s *ttlContainerLister) InvalidateContainerListByCID(id *cid.ID) { } } } + +type cachedIRFetcher ttlNetCache + +func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) *cachedIRFetcher { + const ( + irFetcherCacheSize = 1 // we intend to store only one value + + // Without the cache in the testnet we can see several hundred simultaneous + // requests (neofs-node #1278), so limiting the request rate solves the issue. + // + // Exact request rate doesn't really matter because Inner Ring list update + // happens extremely rare, but there is no side chain events for that as + // for now (neofs-contract v0.15.0 notary disabled env) to monitor it. + irFetcherCacheTTL = 30 * time.Second + ) + + irFetcherCache := newNetworkTTLCache(irFetcherCacheSize, irFetcherCacheTTL, + func(key interface{}) (interface{}, error) { + return f.InnerRingKeys() + }, + ) + + return (*cachedIRFetcher)(irFetcherCache) +} + +// InnerRingKeys returns cached list of Inner Ring keys. If keys are missing in +// the cache or expired, then it returns keys from side chain and updates +// the cache. +func (f *cachedIRFetcher) InnerRingKeys() ([][]byte, error) { + val, err := (*ttlNetCache)(f).get("") + if err != nil { + return nil, err + } + + return val.([][]byte), nil +} diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index 2765a818a..55c79472f 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -348,7 +348,7 @@ func initObjectService(c *cfg) { acl.WithSenderClassifier( acl.NewSenderClassifier( c.log, - irFetcher, + newCachedIRFetcher(irFetcher), c.netMapSource, ), ),