Skip to content

Commit 5f42d38

Browse files
jessegeensdiocas
authored andcommitted
introduced a cache in front of ListProjects to limit the number of calls to the database
1 parent b88da4a commit 5f42d38

File tree

1 file changed

+32
-13
lines changed
  • pkg/projects/manager/sql

1 file changed

+32
-13
lines changed

pkg/projects/manager/sql/sql.go

+32-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import (
2222
"context"
2323
"fmt"
2424
"slices"
25+
"time"
2526

27+
"github.com/ReneKroon/ttlcache/v2"
2628
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
2729
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
2830
"github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions"
@@ -49,13 +51,19 @@ type Config struct {
4951
DBHost string `mapstructure:"db_host"`
5052
DBPort int `mapstructure:"db_port"`
5153
DBName string `mapstructure:"db_name"`
54+
// CacheTTL (seconds) determines how long the list of projects will be stored in a cache
55+
// before a new database query is executed. The default, 0, corresponds to 60 seconds.
56+
CacheTTL int `mapstructure:"cache_ttl"`
5257
}
5358

5459
type mgr struct {
55-
c *Config
56-
db *gorm.DB
60+
c *Config
61+
db *gorm.DB
62+
cache *ttlcache.Cache
5763
}
5864

65+
const cacheKey = "projects/projectsListCache"
66+
5967
// Project represents a project in the DB.
6068
type Project struct {
6169
gorm.Model
@@ -96,26 +104,37 @@ func New(ctx context.Context, m map[string]any) (projects.Catalogue, error) {
96104
return nil, errors.Wrap(err, "Failed to mgirate Project schema")
97105
}
98106

107+
cache := ttlcache.NewCache()
108+
if c.CacheTTL == 0 {
109+
c.CacheTTL = 60
110+
}
111+
cache.SetTTL(time.Duration(c.CacheTTL))
112+
// Even if we get a hit, of course we just want to refresh every 60 seconds
113+
cache.SkipTTLExtensionOnHit(true)
99114
mgr := &mgr{
100-
c: &c,
101-
db: db,
115+
c: &c,
116+
db: db,
117+
cache: cache,
102118
}
103119
return mgr, nil
104120
}
105121

106122
func (m *mgr) ListProjects(ctx context.Context, user *userpb.User) ([]*provider.StorageSpace, error) {
107-
// TODO: we reallyyy should not be loading everything into memory here...
108-
109-
var dbProjects []*Project
110-
111-
query := m.db.Model(&Project{})
112-
res := query.Find(&dbProjects)
113-
if res.Error != nil {
114-
return nil, res.Error
123+
var fetchedProjects []*Project
124+
125+
if res, err := m.cache.Get(cacheKey); err == nil && res != nil {
126+
fetchedProjects = res.([]*Project)
127+
} else {
128+
query := m.db.Model(&Project{})
129+
res := query.Find(&fetchedProjects)
130+
if res.Error != nil {
131+
return nil, res.Error
132+
}
133+
m.cache.Set(cacheKey, fetchedProjects)
115134
}
116135

117136
projects := []*provider.StorageSpace{}
118-
for _, p := range dbProjects {
137+
for _, p := range fetchedProjects {
119138
if perms, ok := projectBelongToUser(user, p); ok {
120139
projects = append(projects, &provider.StorageSpace{
121140
Id: &provider.StorageSpaceId{

0 commit comments

Comments
 (0)