From a1f66e3df25416a1f97a208643db9a3580f9b34f Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 28 Feb 2023 07:29:12 +0800 Subject: [PATCH] feat: update store cache --- api/cache.go | 20 ------------- store/cache.go | 71 ---------------------------------------------- store/shortcut.go | 37 +++++++----------------- store/store.go | 10 +++---- store/user.go | 34 ++++++++++------------ store/workspace.go | 38 +++++++------------------ 6 files changed, 42 insertions(+), 168 deletions(-) delete mode 100644 api/cache.go diff --git a/api/cache.go b/api/cache.go deleted file mode 100644 index 9681d64..0000000 --- a/api/cache.go +++ /dev/null @@ -1,20 +0,0 @@ -package api - -// CacheNamespace is the type of a cache. -type CacheNamespace string - -const ( - // UserCache is the cache type of workspaces. - WorkspaceCache CacheNamespace = "w" - // UserCache is the cache type of users. - UserCache CacheNamespace = "u" - // ShortcutCache is the cache type of shortcuts. - ShortcutCache CacheNamespace = "s" -) - -// CacheService is the service for caches. -type CacheService interface { - FindCache(namespace CacheNamespace, id int, entry interface{}) (bool, error) - UpsertCache(namespace CacheNamespace, id int, entry interface{}) error - DeleteCache(namespace CacheNamespace, id int) -} diff --git a/store/cache.go b/store/cache.go index a4dc3ed..72440ea 100644 --- a/store/cache.go +++ b/store/cache.go @@ -1,72 +1 @@ package store - -import ( - "bytes" - "encoding/binary" - "encoding/gob" - "fmt" - - "github.com/VictoriaMetrics/fastcache" - "github.com/boojack/corgi/api" -) - -var ( - // 64 MiB. - cacheSize = 1024 * 1024 * 64 - _ api.CacheService = (*CacheService)(nil) -) - -// CacheService implements a cache. -type CacheService struct { - cache *fastcache.Cache -} - -// NewCacheService creates a cache service. -func NewCacheService() *CacheService { - return &CacheService{ - cache: fastcache.New(cacheSize), - } -} - -// FindCache finds the value in cache. -func (s *CacheService) FindCache(namespace api.CacheNamespace, id int, entry interface{}) (bool, error) { - buf1 := []byte{0, 0, 0, 0, 0, 0, 0, 0} - binary.LittleEndian.PutUint64(buf1, uint64(id)) - - buf2, has := s.cache.HasGet(nil, append([]byte(namespace), buf1...)) - if has { - dec := gob.NewDecoder(bytes.NewReader(buf2)) - if err := dec.Decode(entry); err != nil { - return false, fmt.Errorf("failed to decode entry for cache namespace: %s, error: %w", namespace, err) - } - return true, nil - } - - return false, nil -} - -// UpsertCache upserts the value to cache. -func (s *CacheService) UpsertCache(namespace api.CacheNamespace, id int, entry interface{}) error { - buf1 := []byte{0, 0, 0, 0, 0, 0, 0, 0} - binary.LittleEndian.PutUint64(buf1, uint64(id)) - - var buf2 bytes.Buffer - enc := gob.NewEncoder(&buf2) - if err := enc.Encode(entry); err != nil { - return fmt.Errorf("failed to encode entry for cache namespace: %s, error: %w", namespace, err) - } - s.cache.Set(append([]byte(namespace), buf1...), buf2.Bytes()) - - return nil -} - -// DeleteCache deletes the cache. -func (s *CacheService) DeleteCache(namespace api.CacheNamespace, id int) { - buf1 := []byte{0, 0, 0, 0, 0, 0, 0, 0} - binary.LittleEndian.PutUint64(buf1, uint64(id)) - - _, has := s.cache.HasGet(nil, append([]byte(namespace), buf1...)) - if has { - s.cache.Del(append([]byte(namespace), buf1...)) - } -} diff --git a/store/shortcut.go b/store/shortcut.go index ce11341..34f473c 100644 --- a/store/shortcut.go +++ b/store/shortcut.go @@ -76,12 +76,8 @@ func (s *Store) CreateShortcut(ctx context.Context, create *api.ShortcutCreate) return nil, FormatError(err) } + s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw) shortcut := shortcutRaw.toShortcut() - - if err := s.cache.UpsertCache(api.ShortcutCache, shortcut.ID, shortcut); err != nil { - return nil, err - } - return shortcut, nil } @@ -101,12 +97,8 @@ func (s *Store) PatchShortcut(ctx context.Context, patch *api.ShortcutPatch) (*a return nil, FormatError(err) } + s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw) shortcut := shortcutRaw.toShortcut() - - if err := s.cache.UpsertCache(api.ShortcutCache, shortcut.ID, shortcut); err != nil { - return nil, err - } - return shortcut, nil } @@ -123,8 +115,9 @@ func (s *Store) FindShortcutList(ctx context.Context, find *api.ShortcutFind) ([ } list := []*api.Shortcut{} - for _, raw := range shortcutRawList { - list = append(list, raw.toShortcut()) + for _, shortcutRaw := range shortcutRawList { + s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw) + list = append(list, shortcutRaw.toShortcut()) } return list, nil @@ -132,13 +125,8 @@ func (s *Store) FindShortcutList(ctx context.Context, find *api.ShortcutFind) ([ func (s *Store) FindShortcut(ctx context.Context, find *api.ShortcutFind) (*api.Shortcut, error) { if find.ID != nil { - shortcut := &api.Shortcut{} - has, err := s.cache.FindCache(api.ShortcutCache, *find.ID, shortcut) - if err != nil { - return nil, err - } - if has { - return shortcut, nil + if cache, ok := s.shortcutCache.Load(*find.ID); ok { + return cache.(*shortcutRaw).toShortcut(), nil } } @@ -157,12 +145,9 @@ func (s *Store) FindShortcut(ctx context.Context, find *api.ShortcutFind) (*api. return nil, &common.Error{Code: common.NotFound, Err: fmt.Errorf("not found")} } - shortcut := list[0].toShortcut() - - if err := s.cache.UpsertCache(api.ShortcutCache, shortcut.ID, shortcut); err != nil { - return nil, err - } - + shortcutRaw := list[0] + s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw) + shortcut := shortcutRaw.toShortcut() return shortcut, nil } @@ -183,7 +168,7 @@ func (s *Store) DeleteShortcut(ctx context.Context, delete *api.ShortcutDelete) } if delete.ID != nil { - s.cache.DeleteCache(api.ShortcutCache, *delete.ID) + s.shortcutCache.Delete(*delete.ID) } return nil diff --git a/store/store.go b/store/store.go index 1b320ae..466a829 100644 --- a/store/store.go +++ b/store/store.go @@ -2,8 +2,8 @@ package store import ( "database/sql" + "sync" - "github.com/boojack/corgi/api" "github.com/boojack/corgi/server/profile" ) @@ -11,16 +11,16 @@ import ( type Store struct { db *sql.DB profile *profile.Profile - cache api.CacheService + + userCache sync.Map // map[int]*userRaw + workspaceCache sync.Map // map[int]*memoRaw + shortcutCache sync.Map // map[int]*shortcutRaw } // New creates a new instance of Store. func New(db *sql.DB, profile *profile.Profile) *Store { - cacheService := NewCacheService() - return &Store{ db: db, profile: profile, - cache: cacheService, } } diff --git a/store/user.go b/store/user.go index 786c9d9..eb011ed 100644 --- a/store/user.go +++ b/store/user.go @@ -58,12 +58,8 @@ func (s *Store) CreateUser(ctx context.Context, create *api.UserCreate) (*api.Us return nil, FormatError(err) } + s.userCache.Store(userRaw.ID, userRaw) user := userRaw.toUser() - - if err := s.cache.UpsertCache(api.UserCache, user.ID, user); err != nil { - return nil, err - } - return user, nil } @@ -83,12 +79,8 @@ func (s *Store) PatchUser(ctx context.Context, patch *api.UserPatch) (*api.User, return nil, FormatError(err) } + s.userCache.Store(userRaw.ID, userRaw) user := userRaw.toUser() - - if err := s.cache.UpsertCache(api.UserCache, user.ID, user); err != nil { - return nil, err - } - return user, nil } @@ -105,14 +97,21 @@ func (s *Store) FindUserList(ctx context.Context, find *api.UserFind) ([]*api.Us } list := []*api.User{} - for _, raw := range userRawList { - list = append(list, raw.toUser()) + for _, userRaw := range userRawList { + s.userCache.Store(userRaw.ID, userRaw) + list = append(list, userRaw.toUser()) } return list, nil } func (s *Store) FindUser(ctx context.Context, find *api.UserFind) (*api.User, error) { + if find.ID != nil { + if cache, ok := s.userCache.Load(*find.ID); ok { + return cache.(*userRaw).toUser(), nil + } + } + tx, err := s.db.BeginTx(ctx, nil) if err != nil { return nil, err @@ -130,11 +129,9 @@ func (s *Store) FindUser(ctx context.Context, find *api.UserFind) (*api.User, er return nil, &common.Error{Code: common.Conflict, Err: fmt.Errorf("found %d users with filter %+v, expect 1", len(list), find)} } - user := list[0].toUser() - if err := s.cache.UpsertCache(api.UserCache, user.ID, user); err != nil { - return nil, err - } - + userRaw := list[0] + s.userCache.Store(userRaw.ID, userRaw) + user := userRaw.toUser() return user, nil } @@ -154,8 +151,7 @@ func (s *Store) DeleteUser(ctx context.Context, delete *api.UserDelete) error { return FormatError(err) } - s.cache.DeleteCache(api.UserCache, delete.ID) - + s.userCache.Delete(delete.ID) return nil } diff --git a/store/workspace.go b/store/workspace.go index d273723..fa10582 100644 --- a/store/workspace.go +++ b/store/workspace.go @@ -58,12 +58,8 @@ func (s *Store) CreateWorkspace(ctx context.Context, create *api.WorkspaceCreate return nil, FormatError(err) } + s.workspaceCache.Store(workspaceRaw.ID, workspaceRaw) workspace := workspaceRaw.toWorkspace() - - if err := s.cache.UpsertCache(api.WorkspaceCache, workspace.ID, workspace); err != nil { - return nil, err - } - return workspace, nil } @@ -83,12 +79,8 @@ func (s *Store) PatchWorkspace(ctx context.Context, patch *api.WorkspacePatch) ( return nil, FormatError(err) } + s.workspaceCache.Store(workspaceRaw.ID, workspaceRaw) workspace := workspaceRaw.toWorkspace() - - if err := s.cache.UpsertCache(api.WorkspaceCache, workspace.ID, workspace); err != nil { - return nil, err - } - return workspace, nil } @@ -105,8 +97,9 @@ func (s *Store) FindWordspaceList(ctx context.Context, find *api.WorkspaceFind) } list := []*api.Workspace{} - for _, raw := range workspaceRawList { - list = append(list, raw.toWorkspace()) + for _, workspaceRaw := range workspaceRawList { + s.workspaceCache.Store(workspaceRaw.ID, workspaceRaw) + list = append(list, workspaceRaw.toWorkspace()) } return list, nil @@ -114,13 +107,8 @@ func (s *Store) FindWordspaceList(ctx context.Context, find *api.WorkspaceFind) func (s *Store) FindWorkspace(ctx context.Context, find *api.WorkspaceFind) (*api.Workspace, error) { if find.ID != nil { - workspace := &api.Workspace{} - has, err := s.cache.FindCache(api.WorkspaceCache, *find.ID, workspace) - if err != nil { - return nil, err - } - if has { - return workspace, nil + if cache, ok := s.workspaceCache.Load(*find.ID); ok { + return cache.(*workspaceRaw).toWorkspace(), nil } } @@ -141,12 +129,9 @@ func (s *Store) FindWorkspace(ctx context.Context, find *api.WorkspaceFind) (*ap return nil, &common.Error{Code: common.Conflict, Err: fmt.Errorf("found %d workspaces with filter %+v, expect 1", len(list), find)} } - workspace := list[0].toWorkspace() - - if err := s.cache.UpsertCache(api.WorkspaceCache, workspace.ID, workspace); err != nil { - return nil, err - } - + workspaceRaw := list[0] + s.workspaceCache.Store(workspaceRaw.ID, workspaceRaw) + workspace := workspaceRaw.toWorkspace() return workspace, nil } @@ -166,8 +151,7 @@ func (s *Store) DeleteWorkspace(ctx context.Context, delete *api.WorkspaceDelete return FormatError(err) } - s.cache.DeleteCache(api.WorkspaceCache, delete.ID) - + s.workspaceCache.Delete(delete.ID) return nil }