From e32facf3e63d376cd53ca1cea4eb6e165bc69e94 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:01:00 +0530 Subject: [PATCH] [server] Refresh fileCount only if trash or usage changed --- server/cmd/museum/main.go | 4 ++- server/ente/cache/user_data_cache.go | 14 ++++++--- server/pkg/controller/usercache/controller.go | 2 ++ server/pkg/controller/usercache/count.go | 29 +++++++++++++++---- server/pkg/repo/trash.go | 10 +++++++ 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 3391b43ecc..2d60a970e9 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -188,7 +188,9 @@ func main() { } userCache := cache2.NewUserCache() - userCacheCtrl := &usercache.Controller{UserCache: userCache, FileRepo: fileRepo, StoreBonusRepo: storagBonusRepo} + userCacheCtrl := &usercache.Controller{UserCache: userCache, FileRepo: fileRepo, + UsageRepo: usageRepo, TrashRepo: trashRepo, + StoreBonusRepo: storagBonusRepo} offerController := offer.NewOfferController(*userRepo, discordController, storagBonusRepo, userCacheCtrl) plans := billing.GetPlans() defaultPlan := billing.GetDefaultPlans(plans) diff --git a/server/ente/cache/user_data_cache.go b/server/ente/cache/user_data_cache.go index 45308f0663..c202d7dd7c 100644 --- a/server/ente/cache/user_data_cache.go +++ b/server/ente/cache/user_data_cache.go @@ -10,20 +10,26 @@ import ( // UserCache struct holds can be used to fileCount various entities for user. type UserCache struct { mu sync.Mutex - fileCache map[string]int64 + fileCache map[string]*FileCountCache bonusCache map[int64]*storagebonus.ActiveStorageBonus } +type FileCountCache struct { + Count int64 + TrashUpdatedAt int64 + Usage int64 +} + // NewUserCache creates a new instance of the UserCache struct. func NewUserCache() *UserCache { return &UserCache{ - fileCache: make(map[string]int64), + fileCache: make(map[string]*FileCountCache), bonusCache: make(map[int64]*storagebonus.ActiveStorageBonus), } } // SetFileCount updates the fileCount with the given userID and fileCount. -func (c *UserCache) SetFileCount(userID, fileCount int64, app ente.App) { +func (c *UserCache) SetFileCount(userID int64, fileCount *FileCountCache, app ente.App) { c.mu.Lock() defer c.mu.Unlock() c.fileCache[cacheKey(userID, app)] = fileCount @@ -44,7 +50,7 @@ func (c *UserCache) GetBonus(userID int64) (*storagebonus.ActiveStorageBonus, bo // GetFileCount retrieves the file count from the fileCount for the given userID. // It returns the file count and a boolean indicating if the value was found. -func (c *UserCache) GetFileCount(userID int64, app ente.App) (int64, bool) { +func (c *UserCache) GetFileCount(userID int64, app ente.App) (*FileCountCache, bool) { c.mu.Lock() defer c.mu.Unlock() count, ok := c.fileCache[cacheKey(userID, app)] diff --git a/server/pkg/controller/usercache/controller.go b/server/pkg/controller/usercache/controller.go index b6645653cd..efce2d11bd 100644 --- a/server/pkg/controller/usercache/controller.go +++ b/server/pkg/controller/usercache/controller.go @@ -14,6 +14,8 @@ import ( // Avoid adding any direct dependencies to the other controller. type Controller struct { FileRepo *repo.FileRepository + UsageRepo *repo.UsageRepository + TrashRepo *repo.TrashRepository StoreBonusRepo *storagebonus.Repository UserCache *cache.UserCache } diff --git a/server/pkg/controller/usercache/count.go b/server/pkg/controller/usercache/count.go index a0f3bb0435..22b5b512ca 100644 --- a/server/pkg/controller/usercache/count.go +++ b/server/pkg/controller/usercache/count.go @@ -2,7 +2,9 @@ package usercache import ( "github.com/ente-io/museum/ente" + "github.com/ente-io/museum/ente/cache" "github.com/ente-io/stacktrace" + "github.com/sirupsen/logrus" ) func (c *Controller) GetUserFileCountWithCache(userID int64, app ente.App) (int64, error) { @@ -10,18 +12,35 @@ func (c *Controller) GetUserFileCountWithCache(userID int64, app ente.App) (int6 if count, ok := c.UserCache.GetFileCount(userID, app); ok { // Cache hit, update the cache asynchronously go func() { - _, _ = c.getUserCountAndUpdateCache(userID, app) + _, _ = c.getUserCountAndUpdateCache(userID, app, count) }() - return count, nil + return count.Count, nil } - return c.getUserCountAndUpdateCache(userID, app) + return c.getUserCountAndUpdateCache(userID, app, nil) } -func (c *Controller) getUserCountAndUpdateCache(userID int64, app ente.App) (int64, error) { +func (c *Controller) getUserCountAndUpdateCache(userID int64, app ente.App, oldCache *cache.FileCountCache) (int64, error) { + usage, err := c.UsageRepo.GetUsage(userID) + if err != nil { + return 0, stacktrace.Propagate(err, "") + } + trashUpdatedAt, err := c.TrashRepo.GetTrashUpdatedAt(userID) + if err != nil { + return 0, stacktrace.Propagate(err, "") + } + if oldCache != nil && oldCache.Usage == usage && oldCache.TrashUpdatedAt == trashUpdatedAt { + logrus.Debugf("Cache hit for user %d", userID) + return oldCache.Count, nil + } count, err := c.FileRepo.GetFileCountForUser(userID, app) if err != nil { return 0, stacktrace.Propagate(err, "") } - c.UserCache.SetFileCount(userID, count, app) + cntCache := &cache.FileCountCache{ + Count: count, + Usage: usage, + TrashUpdatedAt: trashUpdatedAt, + } + c.UserCache.SetFileCount(userID, cntCache, app) return count, nil } diff --git a/server/pkg/repo/trash.go b/server/pkg/repo/trash.go index 3d1cac2bd5..5218caf55d 100644 --- a/server/pkg/repo/trash.go +++ b/server/pkg/repo/trash.go @@ -422,6 +422,16 @@ func (t *TrashRepository) EmptyTrash(ctx context.Context, userID int64, lastUpda return t.QueueRepo.InsertItem(ctx, TrashEmptyQueue, itemID) } +func (t *TrashRepository) GetTrashUpdatedAt(userID int64) (int64, error) { + row := t.DB.QueryRow(`SELECT max(updated_at) FROM trash WHERE user_id = $1`, userID) + var updatedAt int64 + err := row.Scan(&updatedAt) + if errors.Is(err, sql.ErrNoRows) { + return 0, nil + } + return updatedAt, stacktrace.Propagate(err, "") +} + func convertRowsToTrash(rows *sql.Rows) ([]ente.Trash, error) { defer rows.Close() trashFiles := make([]ente.Trash, 0)