mirror of
https://github.com/usememos/memos.git
synced 2024-12-26 23:22:47 +08:00
feat: update store cache (#1066)
* feat: update store cache * chore: update
This commit is contained in:
parent
6e5be6ba75
commit
3590d3f8b6
9 changed files with 109 additions and 228 deletions
3
go.mod
3
go.mod
|
@ -14,7 +14,6 @@ require (
|
|||
require github.com/labstack/echo/v4 v4.9.0
|
||||
|
||||
require (
|
||||
github.com/VictoriaMetrics/fastcache v1.10.0
|
||||
github.com/gorilla/feeds v1.1.1
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/labstack/echo-contrib v0.13.0
|
||||
|
@ -22,10 +21,8 @@ require (
|
|||
|
||||
require (
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
|
|
9
go.sum
9
go.sum
|
@ -1,20 +1,12 @@
|
|||
github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY=
|
||||
github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||
|
@ -88,7 +80,6 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
|
|
|
@ -13,48 +13,6 @@ import (
|
|||
"github.com/usememos/memos/api"
|
||||
)
|
||||
|
||||
func generateRSSFromMemoList(memoList []*api.Memo, baseURL string, profile *api.CustomizedProfile) (string, error) {
|
||||
feed := &feeds.Feed{
|
||||
Title: profile.Name,
|
||||
Link: &feeds.Link{Href: baseURL},
|
||||
Description: profile.Description,
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
feed.Items = make([]*feeds.Item, len(memoList))
|
||||
for i, memo := range memoList {
|
||||
var useTitle = strings.HasPrefix(memo.Content, "# ")
|
||||
|
||||
var title string
|
||||
if useTitle {
|
||||
title = strings.Split(memo.Content, "\n")[0][2:]
|
||||
} else {
|
||||
title = memo.Creator.Username + "-memos-" + strconv.Itoa(memo.ID)
|
||||
}
|
||||
|
||||
var description string
|
||||
if useTitle {
|
||||
var firstLineEnd = strings.Index(memo.Content, "\n")
|
||||
description = memo.Content[firstLineEnd+1:]
|
||||
} else {
|
||||
description = memo.Content
|
||||
}
|
||||
|
||||
feed.Items[i] = &feeds.Item{
|
||||
Title: title,
|
||||
Link: &feeds.Link{Href: baseURL + "/m/" + strconv.Itoa(memo.ID)},
|
||||
Description: description,
|
||||
Created: time.Unix(memo.CreatedTs, 0),
|
||||
}
|
||||
}
|
||||
|
||||
rss, err := feed.ToRss()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return rss, nil
|
||||
}
|
||||
|
||||
func (s *Server) registerRSSRoutes(g *echo.Group) {
|
||||
g.GET("/explore/rss.xml", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
@ -123,6 +81,48 @@ func (s *Server) registerRSSRoutes(g *echo.Group) {
|
|||
})
|
||||
}
|
||||
|
||||
func generateRSSFromMemoList(memoList []*api.Memo, baseURL string, profile *api.CustomizedProfile) (string, error) {
|
||||
feed := &feeds.Feed{
|
||||
Title: profile.Name,
|
||||
Link: &feeds.Link{Href: baseURL},
|
||||
Description: profile.Description,
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
feed.Items = make([]*feeds.Item, len(memoList))
|
||||
for i, memo := range memoList {
|
||||
var useTitle = strings.HasPrefix(memo.Content, "# ")
|
||||
|
||||
var title string
|
||||
if useTitle {
|
||||
title = strings.Split(memo.Content, "\n")[0][2:]
|
||||
} else {
|
||||
title = memo.Creator.Username + "-memos-" + strconv.Itoa(memo.ID)
|
||||
}
|
||||
|
||||
var description string
|
||||
if useTitle {
|
||||
var firstLineEnd = strings.Index(memo.Content, "\n")
|
||||
description = memo.Content[firstLineEnd+1:]
|
||||
} else {
|
||||
description = memo.Content
|
||||
}
|
||||
|
||||
feed.Items[i] = &feeds.Item{
|
||||
Title: title,
|
||||
Link: &feeds.Link{Href: baseURL + "/m/" + strconv.Itoa(memo.ID)},
|
||||
Description: description,
|
||||
Created: time.Unix(memo.CreatedTs, 0),
|
||||
}
|
||||
}
|
||||
|
||||
rss, err := feed.ToRss()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return rss, nil
|
||||
}
|
||||
|
||||
func getSystemCustomizedProfile(ctx context.Context, s *Server) (api.CustomizedProfile, error) {
|
||||
systemStatus := api.SystemStatus{
|
||||
CustomizedProfile: api.CustomizedProfile{
|
||||
|
|
|
@ -1,82 +1,15 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
"github.com/usememos/memos/api"
|
||||
)
|
||||
|
||||
var (
|
||||
// 64 MiB.
|
||||
cacheSize = 1024 * 1024 * 64
|
||||
)
|
||||
|
||||
// CacheService implements a cache.
|
||||
type CacheService struct {
|
||||
cache *fastcache.Cache
|
||||
func getUserSettingCacheKey(userSetting userSettingRaw) string {
|
||||
return fmt.Sprintf("%d-%s", userSetting.UserID, userSetting.Key.String())
|
||||
}
|
||||
|
||||
// CacheNamespace is the type of a cache.
|
||||
type CacheNamespace string
|
||||
|
||||
const (
|
||||
// UserCache is the cache type of users.
|
||||
UserCache CacheNamespace = "u"
|
||||
// MemoCache is the cache type of memos.
|
||||
MemoCache CacheNamespace = "m"
|
||||
// ShortcutCache is the cache type of shortcuts.
|
||||
ShortcutCache CacheNamespace = "s"
|
||||
)
|
||||
|
||||
// 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 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 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 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...))
|
||||
}
|
||||
func getUserSettingFindCacheKey(userSettingFind *api.UserSettingFind) string {
|
||||
return fmt.Sprintf("%d-%s", userSettingFind.UserID, userSettingFind.Key.String())
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ type memoRaw struct {
|
|||
// Domain specific fields
|
||||
Content string
|
||||
Visibility api.Visibility
|
||||
Pinned bool
|
||||
}
|
||||
|
||||
// toMemo creates an instance of Memo based on the memoRaw.
|
||||
|
@ -43,24 +44,15 @@ func (raw *memoRaw) toMemo() *api.Memo {
|
|||
Content: raw.Content,
|
||||
Visibility: raw.Visibility,
|
||||
DisplayTs: raw.CreatedTs,
|
||||
Pinned: raw.Pinned,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Store) ComposeMemo(ctx context.Context, memo *api.Memo) (*api.Memo, error) {
|
||||
memoOrganizer, err := s.FindMemoOrganizer(ctx, &api.MemoOrganizerFind{
|
||||
MemoID: memo.ID,
|
||||
UserID: memo.CreatorID,
|
||||
})
|
||||
if err != nil && common.ErrorCode(err) != common.NotFound {
|
||||
return nil, err
|
||||
} else if memoOrganizer != nil {
|
||||
memo.Pinned = memoOrganizer.Pinned
|
||||
}
|
||||
|
||||
if err = s.ComposeMemoCreator(ctx, memo); err != nil {
|
||||
if err := s.ComposeMemoCreator(ctx, memo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = s.ComposeMemoResourceList(ctx, memo); err != nil {
|
||||
if err := s.ComposeMemoResourceList(ctx, memo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -102,10 +94,7 @@ func (s *Store) CreateMemo(ctx context.Context, create *api.MemoCreate) (*api.Me
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(MemoCache, memoRaw.ID, memoRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.memoCache.Store(memoRaw.ID, memoRaw)
|
||||
memo, err := s.ComposeMemo(ctx, memoRaw.toMemo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -130,10 +119,7 @@ func (s *Store) PatchMemo(ctx context.Context, patch *api.MemoPatch) (*api.Memo,
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(MemoCache, memoRaw.ID, memoRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.memoCache.Store(memoRaw.ID, memoRaw)
|
||||
memo, err := s.ComposeMemo(ctx, memoRaw.toMemo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -169,12 +155,8 @@ func (s *Store) FindMemoList(ctx context.Context, find *api.MemoFind) ([]*api.Me
|
|||
|
||||
func (s *Store) FindMemo(ctx context.Context, find *api.MemoFind) (*api.Memo, error) {
|
||||
if find.ID != nil {
|
||||
memoRaw := &memoRaw{}
|
||||
has, err := s.cache.FindCache(MemoCache, *find.ID, memoRaw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
if memo, ok := s.memoCache.Load(*find.ID); ok {
|
||||
memoRaw := memo.(*memoRaw)
|
||||
memo, err := s.ComposeMemo(ctx, memoRaw.toMemo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -199,10 +181,7 @@ func (s *Store) FindMemo(ctx context.Context, find *api.MemoFind) (*api.Memo, er
|
|||
}
|
||||
|
||||
memoRaw := list[0]
|
||||
if err := s.cache.UpsertCache(MemoCache, memoRaw.ID, memoRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.memoCache.Store(memoRaw.ID, memoRaw)
|
||||
memo, err := s.ComposeMemo(ctx, memoRaw.toMemo())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -229,8 +208,7 @@ func (s *Store) DeleteMemo(ctx context.Context, delete *api.MemoDelete) error {
|
|||
return FormatError(err)
|
||||
}
|
||||
|
||||
s.cache.DeleteCache(MemoCache, delete.ID)
|
||||
|
||||
s.memoCache.Delete(delete.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -309,19 +287,19 @@ func findMemoRawList(ctx context.Context, tx *sql.Tx, find *api.MemoFind) ([]*me
|
|||
where, args := []string{"1 = 1"}, []interface{}{}
|
||||
|
||||
if v := find.ID; v != nil {
|
||||
where, args = append(where, "id = ?"), append(args, *v)
|
||||
where, args = append(where, "memo.id = ?"), append(args, *v)
|
||||
}
|
||||
if v := find.CreatorID; v != nil {
|
||||
where, args = append(where, "creator_id = ?"), append(args, *v)
|
||||
where, args = append(where, "memo.creator_id = ?"), append(args, *v)
|
||||
}
|
||||
if v := find.RowStatus; v != nil {
|
||||
where, args = append(where, "row_status = ?"), append(args, *v)
|
||||
where, args = append(where, "memo.row_status = ?"), append(args, *v)
|
||||
}
|
||||
if v := find.Pinned; v != nil {
|
||||
where = append(where, "id IN (SELECT memo_id FROM memo_organizer WHERE pinned = 1 AND user_id = memo.creator_id)")
|
||||
where = append(where, "memo_organizer.pinned = 1")
|
||||
}
|
||||
if v := find.ContentSearch; v != nil {
|
||||
where, args = append(where, "content LIKE ?"), append(args, "%"+*v+"%")
|
||||
where, args = append(where, "memo.content LIKE ?"), append(args, "%"+*v+"%")
|
||||
}
|
||||
if v := find.VisibilityList; len(v) != 0 {
|
||||
list := []string{}
|
||||
|
@ -329,21 +307,23 @@ func findMemoRawList(ctx context.Context, tx *sql.Tx, find *api.MemoFind) ([]*me
|
|||
list = append(list, fmt.Sprintf("$%d", len(args)+1))
|
||||
args = append(args, visibility)
|
||||
}
|
||||
where = append(where, fmt.Sprintf("visibility in (%s)", strings.Join(list, ",")))
|
||||
where = append(where, fmt.Sprintf("memo.visibility in (%s)", strings.Join(list, ",")))
|
||||
}
|
||||
|
||||
query := `
|
||||
SELECT
|
||||
id,
|
||||
creator_id,
|
||||
created_ts,
|
||||
updated_ts,
|
||||
row_status,
|
||||
content,
|
||||
visibility
|
||||
memo.id,
|
||||
memo.creator_id,
|
||||
memo.created_ts,
|
||||
memo.updated_ts,
|
||||
memo.row_status,
|
||||
memo.content,
|
||||
memo.visibility,
|
||||
memo_organizer.pinned
|
||||
FROM memo
|
||||
LEFT JOIN memo_organizer ON memo_organizer.memo_id = memo.id
|
||||
WHERE ` + strings.Join(where, " AND ") + `
|
||||
ORDER BY created_ts DESC
|
||||
ORDER BY memo.created_ts DESC
|
||||
`
|
||||
rows, err := tx.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
|
@ -354,6 +334,7 @@ func findMemoRawList(ctx context.Context, tx *sql.Tx, find *api.MemoFind) ([]*me
|
|||
memoRawList := make([]*memoRaw, 0)
|
||||
for rows.Next() {
|
||||
var memoRaw memoRaw
|
||||
var pinned sql.NullBool
|
||||
if err := rows.Scan(
|
||||
&memoRaw.ID,
|
||||
&memoRaw.CreatorID,
|
||||
|
@ -362,10 +343,14 @@ func findMemoRawList(ctx context.Context, tx *sql.Tx, find *api.MemoFind) ([]*me
|
|||
&memoRaw.RowStatus,
|
||||
&memoRaw.Content,
|
||||
&memoRaw.Visibility,
|
||||
&pinned,
|
||||
); err != nil {
|
||||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if pinned.Valid {
|
||||
memoRaw.Pinned = pinned.Bool
|
||||
}
|
||||
memoRawList = append(memoRawList, &memoRaw)
|
||||
}
|
||||
|
||||
|
|
|
@ -56,10 +56,7 @@ func (s *Store) CreateShortcut(ctx context.Context, create *api.ShortcutCreate)
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(ShortcutCache, shortcutRaw.ID, shortcutRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw)
|
||||
shortcut := shortcutRaw.toShortcut()
|
||||
|
||||
return shortcut, nil
|
||||
|
@ -81,10 +78,7 @@ func (s *Store) PatchShortcut(ctx context.Context, patch *api.ShortcutPatch) (*a
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(ShortcutCache, shortcutRaw.ID, shortcutRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw)
|
||||
shortcut := shortcutRaw.toShortcut()
|
||||
|
||||
return shortcut, nil
|
||||
|
@ -112,13 +106,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 {
|
||||
shortcutRaw := &shortcutRaw{}
|
||||
has, err := s.cache.FindCache(ShortcutCache, *find.ID, shortcutRaw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
return shortcutRaw.toShortcut(), nil
|
||||
if shortcut, ok := s.shortcutCache.Load(*find.ID); ok {
|
||||
return shortcut.(*shortcutRaw).toShortcut(), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,11 +127,7 @@ func (s *Store) FindShortcut(ctx context.Context, find *api.ShortcutFind) (*api.
|
|||
}
|
||||
|
||||
shortcutRaw := list[0]
|
||||
|
||||
if err := s.cache.UpsertCache(ShortcutCache, shortcutRaw.ID, shortcutRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.shortcutCache.Store(shortcutRaw.ID, shortcutRaw)
|
||||
shortcut := shortcutRaw.toShortcut()
|
||||
|
||||
return shortcut, nil
|
||||
|
@ -164,8 +149,7 @@ func (s *Store) DeleteShortcut(ctx context.Context, delete *api.ShortcutDelete)
|
|||
return FormatError(err)
|
||||
}
|
||||
|
||||
s.cache.DeleteCache(ShortcutCache, *delete.ID)
|
||||
|
||||
s.shortcutCache.Delete(*delete.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package store
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"sync"
|
||||
|
||||
"github.com/usememos/memos/server/profile"
|
||||
)
|
||||
|
@ -11,17 +12,18 @@ import (
|
|||
type Store struct {
|
||||
db *sql.DB
|
||||
profile *profile.Profile
|
||||
cache *CacheService
|
||||
|
||||
userCache sync.Map // map[int]*userRaw
|
||||
userSettingCache sync.Map // map[string]*userSettingRaw
|
||||
memoCache 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,10 +58,8 @@ func (s *Store) ComposeMemoCreator(ctx context.Context, memo *api.Memo) error {
|
|||
user.OpenID = ""
|
||||
user.UserSettingList = nil
|
||||
memo.Creator = user
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateUser(ctx context.Context, create *api.UserCreate) (*api.User, error) {
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
|
@ -78,12 +76,8 @@ func (s *Store) CreateUser(ctx context.Context, create *api.UserCreate) (*api.Us
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(UserCache, userRaw.ID, userRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.userCache.Store(userRaw.ID, userRaw)
|
||||
user := userRaw.toUser()
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
@ -103,12 +97,8 @@ func (s *Store) PatchUser(ctx context.Context, patch *api.UserPatch) (*api.User,
|
|||
return nil, FormatError(err)
|
||||
}
|
||||
|
||||
if err := s.cache.UpsertCache(UserCache, userRaw.ID, userRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.userCache.Store(userRaw.ID, userRaw)
|
||||
user := userRaw.toUser()
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
@ -134,13 +124,8 @@ func (s *Store) FindUserList(ctx context.Context, find *api.UserFind) ([]*api.Us
|
|||
|
||||
func (s *Store) FindUser(ctx context.Context, find *api.UserFind) (*api.User, error) {
|
||||
if find.ID != nil {
|
||||
userRaw := &userRaw{}
|
||||
has, err := s.cache.FindCache(UserCache, *find.ID, userRaw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
return userRaw.toUser(), nil
|
||||
if user, ok := s.userCache.Load(*find.ID); ok {
|
||||
return user.(*userRaw).toUser(), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,13 +145,8 @@ func (s *Store) FindUser(ctx context.Context, find *api.UserFind) (*api.User, er
|
|||
}
|
||||
|
||||
userRaw := list[0]
|
||||
|
||||
if err := s.cache.UpsertCache(UserCache, userRaw.ID, userRaw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.userCache.Store(userRaw.ID, userRaw)
|
||||
user := userRaw.toUser()
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
@ -188,8 +168,7 @@ func (s *Store) DeleteUser(ctx context.Context, delete *api.UserDelete) error {
|
|||
return err
|
||||
}
|
||||
|
||||
s.cache.DeleteCache(UserCache, delete.ID)
|
||||
|
||||
s.userCache.Delete(delete.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ func (s *Store) UpsertUserSetting(ctx context.Context, upsert *api.UserSettingUp
|
|||
return nil, err
|
||||
}
|
||||
|
||||
s.userSettingCache.Store(getUserSettingCacheKey(*userSettingRaw), userSettingRaw)
|
||||
userSetting := userSettingRaw.toUserSetting()
|
||||
|
||||
return userSetting, nil
|
||||
|
@ -57,6 +58,7 @@ func (s *Store) FindUserSettingList(ctx context.Context, find *api.UserSettingFi
|
|||
|
||||
list := []*api.UserSetting{}
|
||||
for _, raw := range userSettingRawList {
|
||||
s.userSettingCache.Store(getUserSettingCacheKey(*raw), raw)
|
||||
list = append(list, raw.toUserSetting())
|
||||
}
|
||||
|
||||
|
@ -64,6 +66,13 @@ func (s *Store) FindUserSettingList(ctx context.Context, find *api.UserSettingFi
|
|||
}
|
||||
|
||||
func (s *Store) FindUserSetting(ctx context.Context, find *api.UserSettingFind) (*api.UserSetting, error) {
|
||||
if userSetting, ok := s.userSettingCache.Load(getUserSettingFindCacheKey(find)); ok {
|
||||
if userSetting == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return userSetting.(*userSettingRaw).toUserSetting(), nil
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, FormatError(err)
|
||||
|
@ -76,12 +85,13 @@ func (s *Store) FindUserSetting(ctx context.Context, find *api.UserSettingFind)
|
|||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
s.userSettingCache.Store(getUserSettingFindCacheKey(find), nil)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userSetting := list[0].toUserSetting()
|
||||
|
||||
return userSetting, nil
|
||||
userSettingRaw := list[0]
|
||||
s.userSettingCache.Store(getUserSettingCacheKey(*userSettingRaw), userSettingRaw)
|
||||
return userSettingRaw.toUserSetting(), nil
|
||||
}
|
||||
|
||||
func upsertUserSetting(ctx context.Context, tx *sql.Tx, upsert *api.UserSettingUpsert) (*userSettingRaw, error) {
|
||||
|
|
Loading…
Reference in a new issue