Skip to content

Commit

Permalink
Implement LRU in-memory caching for listAllNodes endpoint (#164)
Browse files Browse the repository at this point in the history
Co-authored-by: James Kwon <[email protected]>
  • Loading branch information
james03160927 and james03160927 authored Feb 5, 2025
1 parent 0370df0 commit 38a4041
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 54 deletions.
111 changes: 61 additions & 50 deletions drip/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/algolia/algoliasearch-client-go/v3 v3.31.1
github.com/deepmap/oapi-codegen/v2 v2.1.0
github.com/dgraph-io/ristretto/v2 v2.1.0
github.com/getkin/kin-openapi v0.123.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0
Expand All @@ -23,7 +24,7 @@ require (
github.com/newrelic/go-agent/v3/integrations/nrecho-v4 v1.1.3
github.com/oapi-codegen/runtime v1.1.1
github.com/rs/zerolog v1.32.0
github.com/stretchr/testify v1.9.0
github.com/stretchr/testify v1.10.0
github.com/testcontainers/testcontainers-go v0.28.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.28.0
google.golang.org/api v0.165.0
Expand All @@ -49,6 +50,7 @@ require (
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/containerd v1.7.12 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
Expand All @@ -57,6 +59,7 @@ require (
github.com/docker/docker v25.0.2+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
Expand Down
12 changes: 10 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
Expand All @@ -71,6 +73,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen/v2 v2.1.0 h1:I/NMVhJCtuvL9x+S2QzZKpSjGi33oDZwPRdemvOZWyQ=
github.com/deepmap/oapi-codegen/v2 v2.1.0/go.mod h1:R1wL226vc5VmCNJUvMyYr3hJMm5reyv25j952zAVXZ8=
github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I=
github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY=
Expand All @@ -79,6 +85,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down Expand Up @@ -265,8 +273,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8=
github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU=
github.com/testcontainers/testcontainers-go/modules/postgres v0.28.0 h1:ff0s4JdYIdNAVSi/SrpN2Pdt1f+IjIw3AKjbHau8Un4=
Expand Down
71 changes: 71 additions & 0 deletions integration-tests/node_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,77 @@ func TestRegistryNodeVersion(t *testing.T) {
nodeStatus := drip.NodeStatusActive
assert.Equal(t, *node.Status, nodeStatus)
}

t.Run("Cache", func(t *testing.T) {
// create new node version as latest node version
nodeVersion3 := randomNodeVersion(2)
res, err := withMiddleware(authz, impl.PublishNodeVersion)(ctx, drip.PublishNodeVersionRequestObject{
PublisherId: publisherId,
NodeId: *node.Id,
Body: &drip.PublishNodeVersionJSONRequestBody{
PersonalAccessToken: *pat,
Node: *node,
NodeVersion: *nodeVersion3,
},
})
require.IsType(t, drip.PublishNodeVersion201JSONResponse{}, res)
require.NoError(t, err, "should return created node version")

// Retrieve and verify the list of nodes
resNodesCached, err := withMiddleware(authz, impl.ListAllNodes)(ctx, drip.ListAllNodesRequestObject{})
require.NoError(t, err)
assert.Equal(t, resNodes, resNodesCached)
})

t.Run("ForceNoCache", func(t *testing.T) {
// create new node version as latest node version
nodeVersion4 := randomNodeVersion(3)
res, err := withMiddleware(authz, impl.PublishNodeVersion)(ctx, drip.PublishNodeVersionRequestObject{
PublisherId: publisherId,
NodeId: *node.Id,
Body: &drip.PublishNodeVersionJSONRequestBody{
PersonalAccessToken: *pat,
Node: *node,
NodeVersion: *nodeVersion4,
},
})
require.IsType(t, drip.PublishNodeVersion201JSONResponse{}, res)
nodeVersionResp := res.(drip.PublishNodeVersion201JSONResponse)
require.NoError(t, err, "should return created node version")

// Retrieve and verify the list of nodes
resNodes, err := withMiddleware(authz, impl.ListAllNodes)(ctx, drip.ListAllNodesRequestObject{
Params: drip.ListAllNodesParams{
Latest: proto.Bool(true),
},
})
require.NoError(t, err)
require.IsType(t, drip.ListAllNodes200JSONResponse{}, resNodes)
resNodes200 := resNodes.(drip.ListAllNodes200JSONResponse)

// Iterate over each node and assert individual fields
for _, node := range *resNodes200.Nodes {
// Assertions for basic node attributes
assert.Equal(t, *node.Id, *node.Id)
assert.Equal(t, *node.Name, *node.Name)
assert.Equal(t, *node.Repository, *node.Repository)
assert.Equal(t, *node.Description, *node.Description)
assert.Equal(t, *node.Author, *node.Author)
assert.Equal(t, *node.License, *node.License)
assert.Equal(t, *node.Tags, *node.Tags)

// Assert the latest version
assert.Equal(t, *node.LatestVersion.Version, *nodeVersionResp.NodeVersion.Version)
assert.Equal(t, *node.LatestVersion.Changelog, *nodeVersionResp.NodeVersion.Changelog)
assert.Equal(t, *node.LatestVersion.Dependencies, *nodeVersionResp.NodeVersion.Dependencies)
assert.Equal(t, *node.LatestVersion.DownloadUrl, *nodeVersionResp.NodeVersion.DownloadUrl)
assert.Equal(t, *node.LatestVersion.Status, *nodeVersionResp.NodeVersion.Status)

// Status checks
nodeStatus := drip.NodeStatusActive
assert.Equal(t, *node.Status, nodeStatus)
}
})
})

t.Run("Index Nodes", func(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,12 @@ paths:
schema:
type: string
format: date-time
- in: query
name: latest
description: Whether to fetch fresh result from database or use cached one if false
required: false
schema:
type: boolean
responses:
'200':
description: A paginated list of nodes
Expand Down
6 changes: 5 additions & 1 deletion server/implementation/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,11 @@ func (s *DripStrictServerImplementation) ListAllNodes(
}

// List nodes from the registry service
nodeResults, err := s.RegistryService.ListNodes(ctx, s.Client, page, limit, filter)
latest := false
if request.Params.Latest != nil {
latest = *request.Params.Latest
}
nodeResults, err := s.RegistryService.ListNodesWithCache(ctx, s.Client, page, limit, filter, latest)
if err != nil {
log.Ctx(ctx).Error().Msgf("Failed to list nodes w/ err: %v", err)
return drip.ListAllNodes500JSONResponse{Message: "Failed to list nodes", Error: err.Error()}, err
Expand Down
Loading

0 comments on commit 38a4041

Please sign in to comment.