Этот коммит содержится в:
Joram Wilander
2017-02-07 12:36:37 -08:00
коммит произвёл GitHub
родитель eb767d2c1c
Коммит 487bb56a9b
7 изменённых файлов: 61 добавлений и 10 удалений

Просмотреть файл

@@ -136,7 +136,7 @@ func TestCreatePost(t *testing.T) {
} else if rpost9 := resp.Data.(*model.Post); len(rpost9.FileIds) != 3 { } else if rpost9 := resp.Data.(*model.Post); len(rpost9.FileIds) != 3 {
t.Fatal("post should have 3 files") t.Fatal("post should have 3 files")
} else { } else {
infos := store.Must(app.Srv.Store.FileInfo().GetForPost(rpost9.Id)).([]*model.FileInfo) infos := store.Must(app.Srv.Store.FileInfo().GetForPost(rpost9.Id, true)).([]*model.FileInfo)
if len(infos) != 3 { if len(infos) != 3 {
t.Fatal("should've attached all 3 files to post") t.Fatal("should've attached all 3 files to post")
@@ -1184,6 +1184,7 @@ func TestGetMessageForNotification(t *testing.T) {
post.FileIds = model.StringArray{testPng.Id, testJpg1.Id} post.FileIds = model.StringArray{testPng.Id, testJpg1.Id}
store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id)) store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id))
app.Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id)
if message := app.GetMessageForNotification(post, translateFunc); message != "2 images sent: test1.png, test2.jpg" && message != "2 images sent: test2.jpg, test1.png" { if message := app.GetMessageForNotification(post, translateFunc); message != "2 images sent: test1.png, test2.jpg" && message != "2 images sent: test2.jpg, test1.png" {
t.Fatal("should've returned number of images:", message) t.Fatal("should've returned number of images:", message)
} }
@@ -1196,6 +1197,7 @@ func TestGetMessageForNotification(t *testing.T) {
} }
store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id)) store.Must(app.Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id))
app.Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id)
post.FileIds = model.StringArray{testFile.Id, testJpg2.Id} post.FileIds = model.StringArray{testFile.Id, testJpg2.Id}
if message := app.GetMessageForNotification(post, translateFunc); message != "2 files sent: test1.go, test3.jpg" && message != "2 files sent: test3.jpg, test1.go" { if message := app.GetMessageForNotification(post, translateFunc); message != "2 files sent: test1.go, test3.jpg" && message != "2 files sent: test3.jpg, test1.go" {
t.Fatal("should've returned number of mixed files:", message) t.Fatal("should've returned number of mixed files:", message)

Просмотреть файл

@@ -318,7 +318,7 @@ func MigrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
return []*model.FileInfo{} return []*model.FileInfo{}
} else if newPost := result.Data.(*model.PostList).Posts[post.Id]; len(newPost.Filenames) != len(post.Filenames) { } else if newPost := result.Data.(*model.PostList).Posts[post.Id]; len(newPost.Filenames) != len(post.Filenames) {
// Another thread has already created FileInfos for this post, so just return those // Another thread has already created FileInfos for this post, so just return those
if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil { if result := <-Srv.Store.FileInfo().GetForPost(post.Id, false); result.Err != nil {
l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.get_post_file_infos_again.app_error"), post.Id, result.Err) l4g.Error(utils.T("api.file.migrate_filenames_to_file_infos.get_post_file_infos_again.app_error"), post.Id, result.Err)
return []*model.FileInfo{} return []*model.FileInfo{}
} else { } else {

Просмотреть файл

@@ -26,7 +26,7 @@ import (
func SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User) ([]string, *model.AppError) { func SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User) ([]string, *model.AppError) {
pchan := Srv.Store.User().GetAllProfilesInChannel(channel.Id, true) pchan := Srv.Store.User().GetAllProfilesInChannel(channel.Id, true)
fchan := Srv.Store.FileInfo().GetForPost(post.Id) fchan := Srv.Store.FileInfo().GetForPost(post.Id, true)
var profileMap map[string]*model.User var profileMap map[string]*model.User
if result := <-pchan; result.Err != nil { if result := <-pchan; result.Err != nil {
@@ -414,7 +414,7 @@ func GetMessageForNotification(post *model.Post, translateFunc i18n.TranslateFun
// extract the filenames from their paths and determine what type of files are attached // extract the filenames from their paths and determine what type of files are attached
var infos []*model.FileInfo var infos []*model.FileInfo
if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil { if result := <-Srv.Store.FileInfo().GetForPost(post.Id, true); result.Err != nil {
l4g.Warn(utils.T("api.post.get_message_for_notification.get_files.error"), post.Id, result.Err) l4g.Warn(utils.T("api.post.get_message_for_notification.get_files.error"), post.Id, result.Err)
} else { } else {
infos = result.Data.([]*model.FileInfo) infos = result.Data.([]*model.FileInfo)

Просмотреть файл

@@ -457,7 +457,7 @@ func SearchPostsInTeam(terms string, userId string, teamId string, isOrSearch bo
func GetFileInfosForPost(postId string) ([]*model.FileInfo, *model.AppError) { func GetFileInfosForPost(postId string) ([]*model.FileInfo, *model.AppError) {
pchan := Srv.Store.Post().Get(postId) pchan := Srv.Store.Post().Get(postId)
fchan := Srv.Store.FileInfo().GetForPost(postId) fchan := Srv.Store.FileInfo().GetForPost(postId, true)
var infos []*model.FileInfo var infos []*model.FileInfo
if result := <-fchan; result.Err != nil { if result := <-fchan; result.Err != nil {
@@ -476,6 +476,7 @@ func GetFileInfosForPost(postId string) ([]*model.FileInfo, *model.AppError) {
} }
if len(post.Filenames) > 0 { if len(post.Filenames) > 0 {
Srv.Store.FileInfo().InvalidateFileInfosForPostCache(postId)
// The post has Filenames that need to be replaced with FileInfos // The post has Filenames that need to be replaced with FileInfos
infos = MigrateFilenamesToFileInfos(post) infos = MigrateFilenamesToFileInfos(post)
} }

Просмотреть файл

@@ -3,13 +3,26 @@
package store package store
import ( import (
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model" "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
) )
type SqlFileInfoStore struct { type SqlFileInfoStore struct {
*SqlStore *SqlStore
} }
const (
FILE_INFO_CACHE_SIZE = 25000
FILE_INFO_CACHE_SEC = 900 // 15 minutes
)
var fileInfoCache *utils.Cache = utils.NewLru(FILE_INFO_CACHE_SIZE)
func ClearFileCaches() {
fileInfoCache.Purge()
}
func NewSqlFileInfoStore(sqlStore *SqlStore) FileInfoStore { func NewSqlFileInfoStore(sqlStore *SqlStore) FileInfoStore {
s := &SqlFileInfoStore{sqlStore} s := &SqlFileInfoStore{sqlStore}
@@ -119,12 +132,39 @@ func (fs SqlFileInfoStore) GetByPath(path string) StoreChannel {
return storeChannel return storeChannel
} }
func (fs SqlFileInfoStore) GetForPost(postId string) StoreChannel { func (s SqlFileInfoStore) InvalidateFileInfosForPostCache(postId string) {
fileInfoCache.Remove(postId)
}
func (fs SqlFileInfoStore) GetForPost(postId string, allowFromCache bool) StoreChannel {
storeChannel := make(StoreChannel, 1) storeChannel := make(StoreChannel, 1)
go func() { go func() {
result := StoreResult{} result := StoreResult{}
metrics := einterfaces.GetMetricsInterface()
if allowFromCache {
if cacheItem, ok := fileInfoCache.Get(postId); ok {
if metrics != nil {
metrics.IncrementMemCacheHitCounter("File Info Cache")
}
result.Data = cacheItem.([]*model.FileInfo)
storeChannel <- result
close(storeChannel)
return
} else {
if metrics != nil {
metrics.IncrementMemCacheMissCounter("File Info Cache")
}
}
} else {
if metrics != nil {
metrics.IncrementMemCacheMissCounter("File Info Cache")
}
}
var infos []*model.FileInfo var infos []*model.FileInfo
if _, err := fs.GetReplica().Select(&infos, if _, err := fs.GetReplica().Select(&infos,
@@ -140,6 +180,7 @@ func (fs SqlFileInfoStore) GetForPost(postId string) StoreChannel {
result.Err = model.NewLocAppError("SqlFileInfoStore.GetForPost", result.Err = model.NewLocAppError("SqlFileInfoStore.GetForPost",
"store.sql_file_info.get_for_post.app_error", nil, "post_id="+postId+", "+err.Error()) "store.sql_file_info.get_for_post.app_error", nil, "post_id="+postId+", "+err.Error())
} else { } else {
fileInfoCache.AddWithExpiresInSecs(postId, infos, FILE_INFO_CACHE_SEC)
result.Data = infos result.Data = infos
} }

Просмотреть файл

@@ -114,7 +114,13 @@ func TestFileInfoGetForPost(t *testing.T) {
infos[i] = Must(store.FileInfo().Save(info)).(*model.FileInfo) infos[i] = Must(store.FileInfo().Save(info)).(*model.FileInfo)
} }
if result := <-store.FileInfo().GetForPost(postId); result.Err != nil { if result := <-store.FileInfo().GetForPost(postId, false); result.Err != nil {
t.Fatal(result.Err)
} else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 {
t.Fatal("should've returned exactly 2 file infos")
}
if result := <-store.FileInfo().GetForPost(postId, true); result.Err != nil {
t.Fatal(result.Err) t.Fatal(result.Err)
} else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 {
t.Fatal("should've returned exactly 2 file infos") t.Fatal("should've returned exactly 2 file infos")
@@ -157,7 +163,7 @@ func TestFileInfoAttachToPost(t *testing.T) {
info2 = Must(store.FileInfo().Get(info2.Id)).(*model.FileInfo) info2 = Must(store.FileInfo().Get(info2.Id)).(*model.FileInfo)
} }
if result := <-store.FileInfo().GetForPost(postId); result.Err != nil { if result := <-store.FileInfo().GetForPost(postId, false); result.Err != nil {
t.Fatal(result.Err) t.Fatal(result.Err)
} else if infos := result.Data.([]*model.FileInfo); len(infos) != 2 { } else if infos := result.Data.([]*model.FileInfo); len(infos) != 2 {
t.Fatal("should've returned exactly 2 file infos") t.Fatal("should've returned exactly 2 file infos")
@@ -202,7 +208,7 @@ func TestFileInfoDeleteForPost(t *testing.T) {
t.Fatal(result.Err) t.Fatal(result.Err)
} }
if infos := Must(store.FileInfo().GetForPost(postId)).([]*model.FileInfo); len(infos) != 0 { if infos := Must(store.FileInfo().GetForPost(postId, false)).([]*model.FileInfo); len(infos) != 0 {
t.Fatal("shouldn't have returned any file infos") t.Fatal("shouldn't have returned any file infos")
} }
} }

Просмотреть файл

@@ -326,7 +326,8 @@ type FileInfoStore interface {
Save(info *model.FileInfo) StoreChannel Save(info *model.FileInfo) StoreChannel
Get(id string) StoreChannel Get(id string) StoreChannel
GetByPath(path string) StoreChannel GetByPath(path string) StoreChannel
GetForPost(postId string) StoreChannel GetForPost(postId string, allowFromCache bool) StoreChannel
InvalidateFileInfosForPostCache(postId string)
AttachToPost(fileId string, postId string) StoreChannel AttachToPost(fileId string, postId string) StoreChannel
DeleteForPost(postId string) StoreChannel DeleteForPost(postId string) StoreChannel
} }