diff options
| -rw-r--r-- | cache/folders.go | 66 | ||||
| -rw-r--r-- | repository/folders.go | 50 | ||||
| -rw-r--r-- | types/cache.go | 20 |
3 files changed, 133 insertions, 3 deletions
diff --git a/cache/folders.go b/cache/folders.go new file mode 100644 index 0000000..7ff54e6 --- /dev/null +++ b/cache/folders.go @@ -0,0 +1,66 @@ +package cache + +import ( + "lain/types" + "time" + + "github.com/gofiber/fiber/v2" +) + +var folders *types.FolderCache + +func init() { + folders = &types.FolderCache{ + Data: make(map[string]*types.FolderCacheEntry), + TTL: 5 * time.Minute, + } +} + +func GetFolders(userEmail string) ([]fiber.Map, bool) { + folders.Mu.RLock() + defer folders.Mu.RUnlock() + + entry, exists := folders.Data[userEmail] + if !exists { + return nil, false + } + + if time.Now().After(entry.ExpiresAt) { + return nil, false + } + + return entry.Folders, true +} + +func SetFolders(userEmail string, folderList []fiber.Map) { + folders.Mu.Lock() + defer folders.Mu.Unlock() + + now := time.Now() + folders.Data[userEmail] = &types.FolderCacheEntry{ + Folders: folderList, + CachedAt: now, + ExpiresAt: now.Add(folders.TTL), + } +} + +func InvalidateFolders(userEmail string) { + folders.Mu.Lock() + defer folders.Mu.Unlock() + + delete(folders.Data, userEmail) +} + +func InvalidateAllFolders() { + folders.Mu.Lock() + defer folders.Mu.Unlock() + + folders.Data = make(map[string]*types.FolderCacheEntry) +} + +func SetFolderTTL(duration time.Duration) { + folders.Mu.Lock() + defer folders.Mu.Unlock() + + folders.TTL = duration +} diff --git a/repository/folders.go b/repository/folders.go index ba9a478..0da58e0 100644 --- a/repository/folders.go +++ b/repository/folders.go @@ -1,6 +1,7 @@ package repository import ( + "lain/cache" "lain/database" "lain/models" "lain/types" @@ -68,7 +69,16 @@ var folderIcons = map[string]types.FolderIconVariant{ } func GetFolders(userEmail, activeFolder string) []fiber.Map { - syncFolders(userEmail) + if cached, ok := cache.GetFolders(userEmail); ok { + return updateActiveFolder(cached, activeFolder) + } + + var count int64 + database.DB.Model(&models.Folder{}).Where("user_email = ?", userEmail).Count(&count) + + if count == 0 { + syncFolders(userEmail) + } var allFolders []models.Folder database.DB.Where("user_email = ?", userEmail).Find(&allFolders) @@ -108,9 +118,20 @@ func GetFolders(userEmail, activeFolder string) []fiber.Map { } } + cache.SetFolders(userEmail, rootFolders) + return updateActiveFolder(rootFolders, activeFolder) } +func RefreshFolders(userEmail string) error { + cache.InvalidateFolders(userEmail) + err := syncFolders(userEmail) + if err != nil { + return err + } + return nil +} + func GetFolderDisplayName(userEmail, folderPath string) string { decodedPath, _ := url.QueryUnescape(folderPath) @@ -148,6 +169,11 @@ func updateActiveFolder(folders []fiber.Map, activeFolder string) []fiber.Map { decodedActive, _ := url.QueryUnescape(activeFolder) activeLower := strings.ToLower(decodedActive) + foldersCopy := make([]fiber.Map, len(folders)) + for i, folder := range folders { + foldersCopy[i] = copyFolderMap(folder) + } + var updateActive func([]fiber.Map) updateActive = func(folderList []fiber.Map) { for i := range folderList { @@ -159,8 +185,26 @@ func updateActiveFolder(folders []fiber.Map, activeFolder string) []fiber.Map { } } - updateActive(folders) - return folders + updateActive(foldersCopy) + return foldersCopy +} + +func copyFolderMap(folder fiber.Map) fiber.Map { + copy := fiber.Map{} + for k, v := range folder { + if k == "Subfolders" { + if subfolders, ok := v.([]fiber.Map); ok { + subfoldersCopy := make([]fiber.Map, len(subfolders)) + for i, sf := range subfolders { + subfoldersCopy[i] = copyFolderMap(sf) + } + copy[k] = subfoldersCopy + } + } else { + copy[k] = v + } + } + return copy } func sortFolders(folders []models.Folder) { diff --git a/types/cache.go b/types/cache.go new file mode 100644 index 0000000..497151e --- /dev/null +++ b/types/cache.go @@ -0,0 +1,20 @@ +package types + +import ( + "sync" + "time" + + "github.com/gofiber/fiber/v2" +) + +type FolderCacheEntry struct { + Folders []fiber.Map + CachedAt time.Time + ExpiresAt time.Time +} + +type FolderCache struct { + Mu sync.RWMutex + Data map[string]*FolderCacheEntry + TTL time.Duration +} |
