mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: resource store cache (#1742)
This commit is contained in:
@ -40,7 +40,6 @@ type MemoResponse struct {
|
|||||||
|
|
||||||
// Related fields
|
// Related fields
|
||||||
CreatorName string `json:"creatorName"`
|
CreatorName string `json:"creatorName"`
|
||||||
ResourceIDList []int
|
|
||||||
ResourceList []*Resource `json:"resourceList"`
|
ResourceList []*Resource `json:"resourceList"`
|
||||||
RelationList []*MemoRelation `json:"relationList"`
|
RelationList []*MemoRelation `json:"relationList"`
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo").SetInternal(err)
|
||||||
}
|
}
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
memoResponseList := []*api.MemoResponse{}
|
memoResponseList := []*api.MemoResponse{}
|
||||||
for _, memoMessage := range memoMessageList {
|
for _, memoMessage := range memoMessageList {
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusForbidden, "this memo is protected, missing user in session")
|
return echo.NewHTTPError(http.StatusForbidden, "this memo is protected, missing user in session")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to find memo by ID: %v", memoID)).SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to find memo by ID: %v", memoID)).SetInternal(err)
|
||||||
}
|
}
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -461,7 +461,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
memoResponseList := []*api.MemoResponse{}
|
memoResponseList := []*api.MemoResponse{}
|
||||||
for _, memoMessage := range memoMessageList {
|
for _, memoMessage := range memoMessageList {
|
||||||
memoResponse, err := s.ComposeMemoResponse(ctx, convertMemoMessageToMemoResponse(memoMessage))
|
memoResponse, err := s.composeMemoMessageToMemoResponse(ctx, memoMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err)
|
||||||
}
|
}
|
||||||
@ -584,13 +584,8 @@ func convertCreateMemoRequestToMemoMessage(memoCreate *api.CreateMemoRequest) *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertMemoMessageToMemoResponse(memoMessage *store.MemoMessage) *api.MemoResponse {
|
func (s *Server) composeMemoMessageToMemoResponse(ctx context.Context, memoMessage *store.MemoMessage) (*api.MemoResponse, error) {
|
||||||
relationList := []*api.MemoRelation{}
|
memoResponse := &api.MemoResponse{
|
||||||
for _, relation := range memoMessage.RelationList {
|
|
||||||
relationList = append(relationList, convertMemoRelationMessageToMemoRelation(relation))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &api.MemoResponse{
|
|
||||||
ID: memoMessage.ID,
|
ID: memoMessage.ID,
|
||||||
RowStatus: api.RowStatus(memoMessage.RowStatus.String()),
|
RowStatus: api.RowStatus(memoMessage.RowStatus.String()),
|
||||||
CreatorID: memoMessage.CreatorID,
|
CreatorID: memoMessage.CreatorID,
|
||||||
@ -599,12 +594,8 @@ func convertMemoMessageToMemoResponse(memoMessage *store.MemoMessage) *api.MemoR
|
|||||||
Content: memoMessage.Content,
|
Content: memoMessage.Content,
|
||||||
Visibility: api.Visibility(memoMessage.Visibility.String()),
|
Visibility: api.Visibility(memoMessage.Visibility.String()),
|
||||||
Pinned: memoMessage.Pinned,
|
Pinned: memoMessage.Pinned,
|
||||||
ResourceIDList: memoMessage.ResourceIDList,
|
|
||||||
RelationList: relationList,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ComposeMemoResponse(ctx context.Context, memoResponse *api.MemoResponse) (*api.MemoResponse, error) {
|
|
||||||
user, err := s.Store.FindUser(ctx, &api.UserFind{
|
user, err := s.Store.FindUser(ctx, &api.UserFind{
|
||||||
ID: &memoResponse.CreatorID,
|
ID: &memoResponse.CreatorID,
|
||||||
})
|
})
|
||||||
@ -618,16 +609,23 @@ func (s *Server) ComposeMemoResponse(ctx context.Context, memoResponse *api.Memo
|
|||||||
memoResponse.CreatorName = user.Username
|
memoResponse.CreatorName = user.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
memoResponse.ResourceList = []*api.Resource{}
|
relationList := []*api.MemoRelation{}
|
||||||
for _, resourceID := range memoResponse.ResourceIDList {
|
for _, relation := range memoMessage.RelationList {
|
||||||
|
relationList = append(relationList, convertMemoRelationMessageToMemoRelation(relation))
|
||||||
|
}
|
||||||
|
memoResponse.RelationList = relationList
|
||||||
|
|
||||||
|
resourceList := []*api.Resource{}
|
||||||
|
for _, resourceID := range memoMessage.ResourceIDList {
|
||||||
resource, err := s.Store.FindResource(ctx, &api.ResourceFind{
|
resource, err := s.Store.FindResource(ctx, &api.ResourceFind{
|
||||||
ID: &resourceID,
|
ID: &resourceID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
memoResponse.ResourceList = append(memoResponse.ResourceList, resource)
|
resourceList = append(resourceList, resource)
|
||||||
}
|
}
|
||||||
|
memoResponse.ResourceList = resourceList
|
||||||
|
|
||||||
return memoResponse, nil
|
return memoResponse, nil
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,28 @@ func (s *Store) CreateResource(ctx context.Context, create *api.ResourceCreate)
|
|||||||
return resource, nil
|
return resource, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) PatchResource(ctx context.Context, patch *api.ResourcePatch) (*api.Resource, error) {
|
||||||
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, FormatError(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
resourceRaw, err := patchResourceImpl(ctx, tx, patch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return nil, FormatError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.resourceCache.Store(resourceRaw.ID, resourceRaw)
|
||||||
|
resource := resourceRaw.toResource()
|
||||||
|
|
||||||
|
return resource, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Store) FindResourceList(ctx context.Context, find *api.ResourceFind) ([]*api.Resource, error) {
|
func (s *Store) FindResourceList(ctx context.Context, find *api.ResourceFind) ([]*api.Resource, error) {
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -87,6 +109,9 @@ func (s *Store) FindResourceList(ctx context.Context, find *api.ResourceFind) ([
|
|||||||
|
|
||||||
resourceList := []*api.Resource{}
|
resourceList := []*api.Resource{}
|
||||||
for _, raw := range resourceRawList {
|
for _, raw := range resourceRawList {
|
||||||
|
if !find.GetBlob {
|
||||||
|
s.resourceCache.Store(raw.ID, raw)
|
||||||
|
}
|
||||||
resourceList = append(resourceList, raw.toResource())
|
resourceList = append(resourceList, raw.toResource())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +119,11 @@ func (s *Store) FindResourceList(ctx context.Context, find *api.ResourceFind) ([
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) FindResource(ctx context.Context, find *api.ResourceFind) (*api.Resource, error) {
|
func (s *Store) FindResource(ctx context.Context, find *api.ResourceFind) (*api.Resource, error) {
|
||||||
|
if !find.GetBlob && find.ID != nil {
|
||||||
|
if raw, ok := s.resourceCache.Load(find.ID); ok {
|
||||||
|
return raw.(*resourceRaw).toResource(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, FormatError(err)
|
return nil, FormatError(err)
|
||||||
@ -110,6 +140,9 @@ func (s *Store) FindResource(ctx context.Context, find *api.ResourceFind) (*api.
|
|||||||
}
|
}
|
||||||
|
|
||||||
resourceRaw := list[0]
|
resourceRaw := list[0]
|
||||||
|
if !find.GetBlob {
|
||||||
|
s.resourceCache.Store(resourceRaw.ID, resourceRaw)
|
||||||
|
}
|
||||||
resource := resourceRaw.toResource()
|
resource := resourceRaw.toResource()
|
||||||
|
|
||||||
return resource, nil
|
return resource, nil
|
||||||
@ -132,31 +165,11 @@ func (s *Store) DeleteResource(ctx context.Context, delete *api.ResourceDelete)
|
|||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return FormatError(err)
|
return FormatError(err)
|
||||||
}
|
}
|
||||||
|
s.resourceCache.Delete(delete.ID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) PatchResource(ctx context.Context, patch *api.ResourcePatch) (*api.Resource, error) {
|
|
||||||
tx, err := s.db.BeginTx(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, FormatError(err)
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
resourceRaw, err := patchResourceImpl(ctx, tx, patch)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, FormatError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resource := resourceRaw.toResource()
|
|
||||||
|
|
||||||
return resource, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createResourceImpl(ctx context.Context, tx *sql.Tx, create *api.ResourceCreate) (*resourceRaw, error) {
|
func createResourceImpl(ctx context.Context, tx *sql.Tx, create *api.ResourceCreate) (*resourceRaw, error) {
|
||||||
fields := []string{"filename", "blob", "external_link", "type", "size", "creator_id", "internal_path", "public_id"}
|
fields := []string{"filename", "blob", "external_link", "type", "size", "creator_id", "internal_path", "public_id"}
|
||||||
values := []any{create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath, create.PublicID}
|
values := []any{create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath, create.PublicID}
|
||||||
|
@ -17,6 +17,7 @@ type Store struct {
|
|||||||
userSettingCache sync.Map // map[string]*userSettingRaw
|
userSettingCache sync.Map // map[string]*userSettingRaw
|
||||||
shortcutCache sync.Map // map[int]*shortcutRaw
|
shortcutCache sync.Map // map[int]*shortcutRaw
|
||||||
idpCache sync.Map // map[int]*identityProviderMessage
|
idpCache sync.Map // map[int]*identityProviderMessage
|
||||||
|
resourceCache sync.Map // map[int]*resourceRaw
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new instance of Store.
|
// New creates a new instance of Store.
|
||||||
|
Reference in New Issue
Block a user