Skip to content

Commit

Permalink
Merge 1a74785 into 25648dd
Browse files Browse the repository at this point in the history
  • Loading branch information
jwilander committed Feb 7, 2017
2 parents 25648dd + 1a74785 commit 87e5f4a
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 10 deletions.
1 change: 1 addition & 0 deletions api/context.go
Expand Up @@ -582,6 +582,7 @@ func InvalidateAllCaches() {
store.ClearUserCaches()
store.ClearPostCaches()
store.ClearWebhookCaches()
store.ClearFileCaches()
}

func (c *Context) CheckTeamId() {
Expand Down
2 changes: 1 addition & 1 deletion api/file.go
Expand Up @@ -630,7 +630,7 @@ func migrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
return []*model.FileInfo{}
} 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
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)
return []*model.FileInfo{}
} else {
Expand Down
7 changes: 4 additions & 3 deletions api/post.go
Expand Up @@ -616,7 +616,7 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
senderUsername = c.T("system.message.name")
} else {
pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
fchan = Srv.Store.FileInfo().GetForPost(post.Id)
fchan = Srv.Store.FileInfo().GetForPost(post.Id, true)

var profileMap map[string]*model.User
if result := <-pchan; result.Err != nil {
Expand Down Expand Up @@ -1004,7 +1004,7 @@ func getMessageForNotification(post *model.Post, translateFunc i18n.TranslateFun

// extract the filenames from their paths and determine what type of files are attached
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)
} else {
infos = result.Data.([]*model.FileInfo)
Expand Down Expand Up @@ -1691,7 +1691,7 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
}

pchan := Srv.Store.Post().Get(postId)
fchan := Srv.Store.FileInfo().GetForPost(postId)
fchan := Srv.Store.FileInfo().GetForPost(postId, true)

if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
Expand All @@ -1716,6 +1716,7 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
}

if len(post.Filenames) > 0 {
Srv.Store.FileInfo().InvalidateFileInfosForPostCache(postId)
// The post has Filenames that need to be replaced with FileInfos
infos = migrateFilenamesToFileInfos(post)
}
Expand Down
4 changes: 3 additions & 1 deletion api/post_test.go
Expand Up @@ -130,7 +130,7 @@ func TestCreatePost(t *testing.T) {
} else if rpost9 := resp.Data.(*model.Post); len(rpost9.FileIds) != 3 {
t.Fatal("post should have 3 files")
} else {
infos := store.Must(Srv.Store.FileInfo().GetForPost(rpost9.Id)).([]*model.FileInfo)
infos := store.Must(Srv.Store.FileInfo().GetForPost(rpost9.Id, true)).([]*model.FileInfo)

if len(infos) != 3 {
t.Fatal("should've attached all 3 files to post")
Expand Down Expand Up @@ -1267,6 +1267,7 @@ func TestGetMessageForNotification(t *testing.T) {

post.FileIds = model.StringArray{testPng.Id, testJpg1.Id}
store.Must(Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id))
Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id)
if message := 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)
}
Expand All @@ -1280,6 +1281,7 @@ func TestGetMessageForNotification(t *testing.T) {

store.Must(Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id))
post.FileIds = model.StringArray{testFile.Id, testJpg2.Id}
Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id)
if message := 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)
}
Expand Down
42 changes: 41 additions & 1 deletion store/sql_file_info_store.go
Expand Up @@ -3,13 +3,26 @@
package store

import (
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)

type SqlFileInfoStore struct {
*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 {
s := &SqlFileInfoStore{sqlStore}

Expand Down Expand Up @@ -119,11 +132,37 @@ func (fs SqlFileInfoStore) GetByPath(path string) 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)

go func() {
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

Expand All @@ -140,6 +179,7 @@ func (fs SqlFileInfoStore) GetForPost(postId string) StoreChannel {
result.Err = model.NewLocAppError("SqlFileInfoStore.GetForPost",
"store.sql_file_info.get_for_post.app_error", nil, "post_id="+postId+", "+err.Error())
} else {
fileInfoCache.AddWithExpiresInSecs(postId, infos, FILE_INFO_CACHE_SEC)
result.Data = infos
}

Expand Down
12 changes: 9 additions & 3 deletions store/sql_file_info_store_test.go
Expand Up @@ -114,7 +114,13 @@ func TestFileInfoGetForPost(t *testing.T) {
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)
} else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 {
t.Fatal("should've returned exactly 2 file infos")
Expand Down Expand Up @@ -157,7 +163,7 @@ func TestFileInfoAttachToPost(t *testing.T) {
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)
} else if infos := result.Data.([]*model.FileInfo); len(infos) != 2 {
t.Fatal("should've returned exactly 2 file infos")
Expand Down Expand Up @@ -202,7 +208,7 @@ func TestFileInfoDeleteForPost(t *testing.T) {
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")
}
}
3 changes: 2 additions & 1 deletion store/store.go
Expand Up @@ -317,7 +317,8 @@ type FileInfoStore interface {
Save(info *model.FileInfo) StoreChannel
Get(id 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
DeleteForPost(postId string) StoreChannel
}
Expand Down

0 comments on commit 87e5f4a

Please sign in to comment.