diff --git a/engine/access/rpc/backend/backend.go b/engine/access/rpc/backend/backend.go index 9f76a665769..0878f9578b4 100644 --- a/engine/access/rpc/backend/backend.go +++ b/engine/access/rpc/backend/backend.go @@ -2,13 +2,13 @@ package backend import ( "context" + "crypto/md5" //nolint:gosec "fmt" "net" "strconv" "time" - lru "github.com/hashicorp/golang-lru" - lru2 "github.com/hashicorp/golang-lru/v2" + lru "github.com/hashicorp/golang-lru/v2" accessproto "github.com/onflow/flow/protobuf/go/flow/access" "github.com/rs/zerolog" @@ -124,7 +124,7 @@ func New(params Params) (*Backend, error) { retry.Activate() } - loggedScripts, err := lru.New(DefaultLoggedScriptsCacheSize) + loggedScripts, err := lru.New[[md5.Size]byte, time.Time](DefaultLoggedScriptsCacheSize) if err != nil { return nil, fmt.Errorf("failed to initialize script logging cache: %w", err) } @@ -138,9 +138,9 @@ func New(params Params) (*Backend, error) { archivePorts[idx] = port } - var txResCache *lru2.Cache[flow.Identifier, *access.TransactionResult] + var txResCache *lru.Cache[flow.Identifier, *access.TransactionResult] if params.TxResultCacheSize > 0 { - txResCache, err = lru2.New[flow.Identifier, *access.TransactionResult](int(params.TxResultCacheSize)) + txResCache, err = lru.New[flow.Identifier, *access.TransactionResult](int(params.TxResultCacheSize)) if err != nil { return nil, fmt.Errorf("failed to init cache for transaction results: %w", err) } @@ -246,14 +246,13 @@ func NewCache( log zerolog.Logger, accessMetrics module.AccessMetrics, connectionPoolSize uint, -) (*lru.Cache, uint, error) { +) (*lru.Cache[string, *connection.CachedClient], uint, error) { - var cache *lru.Cache + var cache *lru.Cache[string, *connection.CachedClient] cacheSize := connectionPoolSize if cacheSize > 0 { var err error - cache, err = lru.NewWithEvict(int(cacheSize), func(_, evictedValue interface{}) { - store := evictedValue.(*connection.CachedClient) + cache, err = lru.NewWithEvict(int(cacheSize), func(_ string, store *connection.CachedClient) { store.Close() log.Debug().Str("grpc_conn_evicted", store.Address).Msg("closing grpc connection evicted from pool") if accessMetrics != nil { diff --git a/engine/access/rpc/backend/backend_scripts.go b/engine/access/rpc/backend/backend_scripts.go index bdff9beb8d7..be60d1ae803 100644 --- a/engine/access/rpc/backend/backend_scripts.go +++ b/engine/access/rpc/backend/backend_scripts.go @@ -8,7 +8,7 @@ import ( "time" "github.com/hashicorp/go-multierror" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/onflow/flow/protobuf/go/flow/access" execproto "github.com/onflow/flow/protobuf/go/flow/execution" "github.com/rs/zerolog" @@ -33,7 +33,7 @@ type backendScripts struct { connFactory connection.ConnectionFactory log zerolog.Logger metrics module.BackendScriptsMetrics - loggedScripts *lru.Cache + loggedScripts *lru.Cache[[md5.Size]byte, time.Time] archiveAddressList []string archivePorts []uint scriptExecValidation bool @@ -309,15 +309,14 @@ func (b *backendScripts) executeScriptOnAvailableExecutionNodes( } // shouldLogScript checks if the script hash is unique in the time window -func (b *backendScripts) shouldLogScript(execTime time.Time, scriptHash [16]byte) bool { - rawTimestamp, seen := b.loggedScripts.Get(scriptHash) - if !seen || rawTimestamp == nil { - return true - } else { +func (b *backendScripts) shouldLogScript(execTime time.Time, scriptHash [md5.Size]byte) bool { + timestamp, seen := b.loggedScripts.Get(scriptHash) + if seen { // safe cast - timestamp := rawTimestamp.(time.Time) return execTime.Sub(timestamp) >= uniqueScriptLoggingTimeWindow } + return true + } func (b *backendScripts) tryExecuteScriptOnExecutionNode( diff --git a/engine/access/rpc/backend/backend_transactions.go b/engine/access/rpc/backend/backend_transactions.go index e0ae9e96fad..38944173b69 100644 --- a/engine/access/rpc/backend/backend_transactions.go +++ b/engine/access/rpc/backend/backend_transactions.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - lru2 "github.com/hashicorp/golang-lru/v2" + lru "github.com/hashicorp/golang-lru/v2" accessproto "github.com/onflow/flow/protobuf/go/flow/access" "github.com/onflow/flow/protobuf/go/flow/entities" execproto "github.com/onflow/flow/protobuf/go/flow/execution" @@ -41,7 +41,7 @@ type backendTransactions struct { previousAccessNodes []accessproto.AccessAPIClient log zerolog.Logger nodeCommunicator Communicator - txResultCache *lru2.Cache[flow.Identifier, *access.TransactionResult] + txResultCache *lru.Cache[flow.Identifier, *access.TransactionResult] } // SendTransaction forwards the transaction to the collection node diff --git a/engine/access/rpc/connection/cache.go b/engine/access/rpc/connection/cache.go index 9aa53d3d251..133cac9dd12 100644 --- a/engine/access/rpc/connection/cache.go +++ b/engine/access/rpc/connection/cache.go @@ -4,7 +4,7 @@ import ( "sync" "time" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/atomic" "google.golang.org/grpc" ) @@ -38,12 +38,12 @@ func (s *CachedClient) Close() { // Cache represents a cache of CachedClient instances with a given maximum size. type Cache struct { - cache *lru.Cache + cache *lru.Cache[string, *CachedClient] size int } // NewCache creates a new Cache with the specified maximum size and the underlying LRU cache. -func NewCache(cache *lru.Cache, size int) *Cache { +func NewCache(cache *lru.Cache[string, *CachedClient], size int) *Cache { return &Cache{ cache: cache, size: size, @@ -57,7 +57,7 @@ func (c *Cache) Get(address string) (*CachedClient, bool) { if !ok { return nil, false } - return val.(*CachedClient), true + return val, true } // GetOrAdd atomically gets the CachedClient for the given address from the cache, or adds a new one @@ -71,7 +71,7 @@ func (c *Cache) GetOrAdd(address string, timeout time.Duration) (*CachedClient, val, existed, _ := c.cache.PeekOrAdd(address, client) if existed { - return val.(*CachedClient), true + return val, true } client.Address = address diff --git a/engine/access/rpc/connection/connection_test.go b/engine/access/rpc/connection/connection_test.go index a961816605e..b22bd237318 100644 --- a/engine/access/rpc/connection/connection_test.go +++ b/engine/access/rpc/connection/connection_test.go @@ -4,29 +4,24 @@ import ( "context" "fmt" "net" - "strconv" - "strings" "sync" "testing" "time" - "github.com/sony/gobreaker" - - "go.uber.org/atomic" - "pgregory.net/rapid" - - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/onflow/flow/protobuf/go/flow/access" "github.com/onflow/flow/protobuf/go/flow/execution" + "github.com/sony/gobreaker" "github.com/stretchr/testify/assert" testifymock "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "go.uber.org/atomic" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/status" + "pgregory.net/rapid" - "github.com/onflow/flow-go/engine/access/mock" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/utils/unittest" ) @@ -72,6 +67,14 @@ func TestProxyAccessAPI(t *testing.T) { assert.Equal(t, resp, expected) } +func getCache(t *testing.T, cacheSize int) *lru.Cache[string, *CachedClient] { + cache, err := lru.NewWithEvict[string, *CachedClient](cacheSize, func(_ string, client *CachedClient) { + client.Close() + }) + require.NoError(t, err) + return cache +} + func TestProxyExecutionAPI(t *testing.T) { // create an execution node en := new(executionNode) @@ -129,10 +132,7 @@ func TestProxyAccessAPIConnectionReuse(t *testing.T) { connectionFactory.CollectionGRPCPort = cn.port // set the connection pool cache size cacheSize := 1 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() @@ -184,10 +184,7 @@ func TestProxyExecutionAPIConnectionReuse(t *testing.T) { connectionFactory.ExecutionGRPCPort = en.port // set the connection pool cache size cacheSize := 5 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -245,10 +242,7 @@ func TestExecutionNodeClientTimeout(t *testing.T) { connectionFactory.ExecutionNodeGRPCTimeout = timeout // set the connection pool cache size cacheSize := 5 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -294,10 +288,7 @@ func TestCollectionNodeClientTimeout(t *testing.T) { connectionFactory.CollectionNodeGRPCTimeout = timeout // set the connection pool cache size cacheSize := 5 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -343,10 +334,8 @@ func TestConnectionPoolFull(t *testing.T) { connectionFactory.CollectionGRPCPort = cn1.port // set the connection pool cache size cacheSize := 2 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) + // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -419,10 +408,8 @@ func TestConnectionPoolStale(t *testing.T) { connectionFactory.CollectionGRPCPort = cn.port // set the connection pool cache size cacheSize := 5 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) + // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -488,7 +475,7 @@ func TestExecutionNodeClientClosedGracefully(t *testing.T) { } // Add rapid test, to check graceful close on different number of requests - rapid.Check(t, func(t *rapid.T) { + rapid.Check(t, func(tt *rapid.T) { en, closer := createExecNode() defer closer() @@ -508,10 +495,8 @@ func TestExecutionNodeClientClosedGracefully(t *testing.T) { connectionFactory.ExecutionNodeGRPCTimeout = time.Second // set the connection pool cache size cacheSize := 1 - cache, _ := lru.NewWithEvict(cacheSize, func(_, evictedValue interface{}) { - evictedValue.(*CachedClient).Close() - }) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) + // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -530,7 +515,7 @@ func TestExecutionNodeClientClosedGracefully(t *testing.T) { ctx := context.Background() // Generate random number of requests - nofRequests := rapid.IntRange(10, 100).Draw(t, "nofRequests").(int) + nofRequests := rapid.IntRange(10, 100).Draw(tt, "nofRequests").(int) reqCompleted := atomic.NewUint64(0) var waitGroup sync.WaitGroup @@ -592,10 +577,8 @@ func TestExecutionEvictingCacheClients(t *testing.T) { connectionFactory.CollectionNodeGRPCTimeout = 5 * time.Second // Set the connection pool cache size cacheSize := 1 - cache, err := lru.New(cacheSize) - require.NoError(t, err) - connectionCache := NewCache(cache, cacheSize) + connectionCache := NewCache(getCache(t, cacheSize), cacheSize) // set metrics reporting connectionFactory.AccessMetrics = metrics.NewNoopCollector() connectionFactory.Manager = NewManager( @@ -614,9 +597,8 @@ func TestExecutionEvictingCacheClients(t *testing.T) { ctx := context.Background() // Retrieve the cached client from the cache - result, _ := cache.Get(clientAddress) - cachedClient := result.(*CachedClient) - + cachedClient, ok := connectionCache.Get(clientAddress) + require.True(t, ok) // Schedule the invalidation of the access API client after a delay time.AfterFunc(250*time.Millisecond, func() { // Invalidate the access API client @@ -642,7 +624,7 @@ func TestExecutionEvictingCacheClients(t *testing.T) { changed := cachedClient.ClientConn.WaitForStateChange(ctx, connectivity.Ready) assert.True(t, changed) assert.Equal(t, connectivity.Shutdown, cachedClient.ClientConn.GetState()) - assert.Equal(t, 0, cache.Len()) + assert.Equal(t, 0, connectionCache.Len()) } // TestCircuitBreakerExecutionNode tests the circuit breaker state changes for execution nodes. @@ -671,7 +653,8 @@ func TestCircuitBreakerExecutionNode(t *testing.T) { // Set the connection pool cache size. cacheSize := 1 - connectionCache, _ := lru.New(cacheSize) + connectionCache, err := lru.New[string, *CachedClient](cacheSize) + require.NoError(t, err) connectionFactory.Manager = NewManager( NewCache(connectionCache, cacheSize), @@ -755,7 +738,8 @@ func TestCircuitBreakerCollectionNode(t *testing.T) { // Set the connection pool cache size. cacheSize := 1 - connectionCache, _ := lru.New(cacheSize) + connectionCache, err := lru.New[string, *CachedClient](cacheSize) + require.NoError(t, err) connectionFactory.Manager = NewManager( NewCache(connectionCache, cacheSize), @@ -812,79 +796,3 @@ func TestCircuitBreakerCollectionNode(t *testing.T) { assert.Greater(t, requestTimeout, duration) assert.Equal(t, nil, err) } - -// node mocks a flow node that runs a GRPC server -type node struct { - server *grpc.Server - listener net.Listener - port uint -} - -func (n *node) setupNode(t *testing.T) { - n.server = grpc.NewServer() - listener, err := net.Listen("tcp4", unittest.DefaultAddress) - assert.NoError(t, err) - n.listener = listener - assert.Eventually(t, func() bool { - return !strings.HasSuffix(listener.Addr().String(), ":0") - }, time.Second*4, 10*time.Millisecond) - - _, port, err := net.SplitHostPort(listener.Addr().String()) - assert.NoError(t, err) - portAsUint, err := strconv.ParseUint(port, 10, 32) - assert.NoError(t, err) - n.port = uint(portAsUint) -} - -func (n *node) start(t *testing.T) { - // using a wait group here to ensure the goroutine has started before returning. Otherwise, - // there's a race condition where the server is sometimes stopped before it has started - wg := sync.WaitGroup{} - wg.Add(1) - go func() { - wg.Done() - err := n.server.Serve(n.listener) - assert.NoError(t, err) - }() - unittest.RequireReturnsBefore(t, wg.Wait, 10*time.Millisecond, "could not start goroutine on time") -} - -func (n *node) stop(t *testing.T) { - if n.server != nil { - n.server.Stop() - } -} - -type executionNode struct { - node - handler *mock.ExecutionAPIServer -} - -func (en *executionNode) start(t *testing.T) { - en.setupNode(t) - handler := new(mock.ExecutionAPIServer) - execution.RegisterExecutionAPIServer(en.server, handler) - en.handler = handler - en.node.start(t) -} - -func (en *executionNode) stop(t *testing.T) { - en.node.stop(t) -} - -type collectionNode struct { - node - handler *mock.AccessAPIServer -} - -func (cn *collectionNode) start(t *testing.T) { - cn.setupNode(t) - handler := new(mock.AccessAPIServer) - access.RegisterAccessAPIServer(cn.server, handler) - cn.handler = handler - cn.node.start(t) -} - -func (cn *collectionNode) stop(t *testing.T) { - cn.node.stop(t) -} diff --git a/engine/access/rpc/connection/node_mock.go b/engine/access/rpc/connection/node_mock.go new file mode 100644 index 00000000000..e8929ab6ef3 --- /dev/null +++ b/engine/access/rpc/connection/node_mock.go @@ -0,0 +1,94 @@ +package connection + +import ( + "net" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/onflow/flow/protobuf/go/flow/access" + "github.com/onflow/flow/protobuf/go/flow/execution" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" + + "github.com/onflow/flow-go/engine/access/mock" + "github.com/onflow/flow-go/utils/unittest" +) + +// node mocks a flow node that runs a GRPC server +type node struct { + server *grpc.Server + listener net.Listener + port uint +} + +func (n *node) setupNode(t *testing.T) { + n.server = grpc.NewServer() + listener, err := net.Listen("tcp4", unittest.DefaultAddress) + assert.NoError(t, err) + n.listener = listener + assert.Eventually(t, func() bool { + return !strings.HasSuffix(listener.Addr().String(), ":0") + }, time.Second*4, 10*time.Millisecond) + + _, port, err := net.SplitHostPort(listener.Addr().String()) + assert.NoError(t, err) + portAsUint, err := strconv.ParseUint(port, 10, 32) + assert.NoError(t, err) + n.port = uint(portAsUint) +} + +func (n *node) start(t *testing.T) { + // using a wait group here to ensure the goroutine has started before returning. Otherwise, + // there's a race condition where the server is sometimes stopped before it has started + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + wg.Done() + err := n.server.Serve(n.listener) + assert.NoError(t, err) + }() + unittest.RequireReturnsBefore(t, wg.Wait, 10*time.Millisecond, "could not start goroutine on time") +} + +func (n *node) stop(t *testing.T) { + if n.server != nil { + n.server.Stop() + } +} + +type executionNode struct { + node + handler *mock.ExecutionAPIServer +} + +func (en *executionNode) start(t *testing.T) { + en.setupNode(t) + handler := new(mock.ExecutionAPIServer) + execution.RegisterExecutionAPIServer(en.server, handler) + en.handler = handler + en.node.start(t) +} + +func (en *executionNode) stop(t *testing.T) { + en.node.stop(t) +} + +type collectionNode struct { + node + handler *mock.AccessAPIServer +} + +func (cn *collectionNode) start(t *testing.T) { + cn.setupNode(t) + handler := new(mock.AccessAPIServer) + access.RegisterAccessAPIServer(cn.server, handler) + cn.handler = handler + cn.node.start(t) +} + +func (cn *collectionNode) stop(t *testing.T) { + cn.node.stop(t) +} diff --git a/engine/consensus/approvals/approvals_lru_cache.go b/engine/consensus/approvals/approvals_lru_cache.go index f4b84d008a1..26fccc715ff 100644 --- a/engine/consensus/approvals/approvals_lru_cache.go +++ b/engine/consensus/approvals/approvals_lru_cache.go @@ -3,7 +3,7 @@ package approvals import ( "sync" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "github.com/onflow/flow-go/model/flow" ) @@ -11,7 +11,7 @@ import ( // LruCache is a wrapper over `simplelru.LRUCache` that provides needed api for processing result approvals // Extends functionality of `simplelru.LRUCache` by introducing additional index for quicker access. type LruCache struct { - lru simplelru.LRUCache + lru simplelru.LRUCache[flow.Identifier, *flow.ResultApproval] lock sync.RWMutex // secondary index by result id, since multiple approvals could // reference same result @@ -21,8 +21,7 @@ type LruCache struct { func NewApprovalsLRUCache(limit uint) *LruCache { byResultID := make(map[flow.Identifier]map[flow.Identifier]struct{}) // callback has to be called while we are holding lock - lru, _ := simplelru.NewLRU(int(limit), func(key interface{}, value interface{}) { - approval := value.(*flow.ResultApproval) + lru, _ := simplelru.NewLRU(int(limit), func(key flow.Identifier, approval *flow.ResultApproval) { delete(byResultID[approval.Body.ExecutionResultID], approval.Body.PartialID()) if len(byResultID[approval.Body.ExecutionResultID]) == 0 { delete(byResultID, approval.Body.ExecutionResultID) @@ -40,7 +39,7 @@ func (c *LruCache) Peek(approvalID flow.Identifier) *flow.ResultApproval { // check if we have it in the cache resource, cached := c.lru.Peek(approvalID) if cached { - return resource.(*flow.ResultApproval) + return resource } return nil @@ -52,7 +51,7 @@ func (c *LruCache) Get(approvalID flow.Identifier) *flow.ResultApproval { // check if we have it in the cache resource, cached := c.lru.Get(approvalID) if cached { - return resource.(*flow.ResultApproval) + return resource } return nil @@ -74,7 +73,7 @@ func (c *LruCache) TakeByResultID(resultID flow.Identifier) []*flow.ResultApprov // no need to cleanup secondary index since it will be // cleaned up in evict callback _ = c.lru.Remove(approvalID) - approvals = append(approvals, resource.(*flow.ResultApproval)) + approvals = append(approvals, resource) } } diff --git a/fvm/storage/derived/derived_chain_data.go b/fvm/storage/derived/derived_chain_data.go index a3ec9a488df..8bcf0b03d00 100644 --- a/fvm/storage/derived/derived_chain_data.go +++ b/fvm/storage/derived/derived_chain_data.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "github.com/onflow/flow-go/model/flow" ) @@ -21,11 +21,11 @@ type DerivedChainData struct { // on Get. mutex sync.Mutex - lru *simplelru.LRU + lru *simplelru.LRU[flow.Identifier, *DerivedBlockData] } func NewDerivedChainData(chainCacheSize uint) (*DerivedChainData, error) { - lru, err := simplelru.NewLRU(int(chainCacheSize), nil) + lru, err := simplelru.NewLRU[flow.Identifier, *DerivedBlockData](int(chainCacheSize), nil) if err != nil { return nil, fmt.Errorf("cannot create LRU cache: %w", err) } @@ -40,7 +40,7 @@ func (chain *DerivedChainData) unsafeGet( ) *DerivedBlockData { currentEntry, ok := chain.lru.Get(currentBlockId) if ok { - return currentEntry.(*DerivedBlockData) + return currentEntry } return nil @@ -70,7 +70,7 @@ func (chain *DerivedChainData) GetOrCreateDerivedBlockData( var current *DerivedBlockData parentEntry, ok := chain.lru.Get(parentBlockId) if ok { - current = parentEntry.(*DerivedBlockData).NewChildDerivedBlockData() + current = parentEntry.NewChildDerivedBlockData() } else { current = NewEmptyDerivedBlockData(0) } diff --git a/module/trace/trace.go b/module/trace/trace.go index c734f4a699b..ee6546d5742 100644 --- a/module/trace/trace.go +++ b/module/trace/trace.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/rs/zerolog" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -41,7 +41,7 @@ type Tracer struct { tracer trace.Tracer shutdown func(context.Context) error log zerolog.Logger - spanCache *lru.Cache + spanCache *lru.Cache[flow.Identifier, trace.Span] chainID string sensitivity uint } @@ -88,7 +88,7 @@ func NewTracer( log.Debug().Err(err).Msg("tracing error") })) - spanCache, err := lru.New(int(DefaultEntityCacheSize)) + spanCache, err := lru.New[flow.Identifier, trace.Span](int(DefaultEntityCacheSize)) if err != nil { return nil, err } @@ -157,8 +157,7 @@ func (t *Tracer) entityRootSpan( trace.Span, ) { if c, ok := t.spanCache.Get(entityID); ok { - span := c.(trace.Span) - return trace.ContextWithSpan(ctx, span), span + return trace.ContextWithSpan(ctx, c), c } traceID := (*trace.TraceID)(entityID[:16])