Merge remote-tracking branch 'origin/master' into advanced-permissions-phase-1
Этот коммит содержится в:
@@ -4,13 +4,13 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"bytes"
|
||||
"sync"
|
||||
|
||||
l4g "github.com/alecthomas/log4go"
|
||||
"github.com/mattermost/mattermost-server/einterfaces"
|
||||
@@ -21,7 +21,11 @@ import (
|
||||
|
||||
type SqlPostStore struct {
|
||||
SqlStore
|
||||
metrics einterfaces.MetricsInterface
|
||||
metrics einterfaces.MetricsInterface
|
||||
lastPostTimeCache *utils.Cache
|
||||
lastPostsCache *utils.Cache
|
||||
maxPostSizeOnce sync.Once
|
||||
maxPostSizeCached int
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -32,12 +36,9 @@ const (
|
||||
LAST_POSTS_CACHE_SEC = 900 // 15 minutes
|
||||
)
|
||||
|
||||
var lastPostTimeCache = utils.NewLru(LAST_POST_TIME_CACHE_SIZE)
|
||||
var lastPostsCache = utils.NewLru(LAST_POSTS_CACHE_SIZE)
|
||||
|
||||
func (s SqlPostStore) ClearCaches() {
|
||||
lastPostTimeCache.Purge()
|
||||
lastPostsCache.Purge()
|
||||
func (s *SqlPostStore) ClearCaches() {
|
||||
s.lastPostTimeCache.Purge()
|
||||
s.lastPostsCache.Purge()
|
||||
|
||||
if s.metrics != nil {
|
||||
s.metrics.IncrementMemCacheInvalidationCounter("Last Post Time - Purge")
|
||||
@@ -47,8 +48,11 @@ func (s SqlPostStore) ClearCaches() {
|
||||
|
||||
func NewSqlPostStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.PostStore {
|
||||
s := &SqlPostStore{
|
||||
SqlStore: sqlStore,
|
||||
metrics: metrics,
|
||||
SqlStore: sqlStore,
|
||||
metrics: metrics,
|
||||
lastPostTimeCache: utils.NewLru(LAST_POST_TIME_CACHE_SIZE),
|
||||
lastPostsCache: utils.NewLru(LAST_POSTS_CACHE_SIZE),
|
||||
maxPostSizeCached: model.POST_MESSAGE_MAX_RUNES_V1,
|
||||
}
|
||||
|
||||
for _, db := range sqlStore.GetAllConns() {
|
||||
@@ -59,18 +63,18 @@ func NewSqlPostStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) st
|
||||
table.ColMap("RootId").SetMaxSize(26)
|
||||
table.ColMap("ParentId").SetMaxSize(26)
|
||||
table.ColMap("OriginalId").SetMaxSize(26)
|
||||
table.ColMap("Message").SetMaxSize(4000)
|
||||
table.ColMap("Message").SetMaxSize(model.POST_MESSAGE_MAX_BYTES_V2)
|
||||
table.ColMap("Type").SetMaxSize(26)
|
||||
table.ColMap("Hashtags").SetMaxSize(1000)
|
||||
table.ColMap("Props").SetMaxSize(8000)
|
||||
table.ColMap("Filenames").SetMaxSize(4000)
|
||||
table.ColMap("Filenames").SetMaxSize(model.POST_FILENAMES_MAX_RUNES)
|
||||
table.ColMap("FileIds").SetMaxSize(150)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s SqlPostStore) CreateIndexesIfNotExists() {
|
||||
func (s *SqlPostStore) CreateIndexesIfNotExists() {
|
||||
s.CreateIndexIfNotExists("idx_posts_update_at", "Posts", "UpdateAt")
|
||||
s.CreateIndexIfNotExists("idx_posts_create_at", "Posts", "CreateAt")
|
||||
s.CreateIndexIfNotExists("idx_posts_delete_at", "Posts", "DeleteAt")
|
||||
@@ -86,15 +90,23 @@ func (s SqlPostStore) CreateIndexesIfNotExists() {
|
||||
s.CreateFullTextIndexIfNotExists("idx_posts_hashtags_txt", "Posts", "Hashtags")
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Save(post *model.Post) store.StoreChannel {
|
||||
func (s *SqlPostStore) Save(post *model.Post) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if len(post.Id) > 0 {
|
||||
result.Err = model.NewAppError("SqlPostStore.Save", "store.sql_post.save.existing.app_error", nil, "id="+post.Id, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var maxPostSize int
|
||||
if result := <-s.GetMaxPostSize(); result.Err != nil {
|
||||
result.Err = model.NewAppError("SqlPostStore.Save", "store.sql_post.save.app_error", nil, "id="+post.Id+", "+result.Err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else {
|
||||
maxPostSize = result.Data.(int)
|
||||
}
|
||||
|
||||
post.PreSave()
|
||||
if result.Err = post.IsValid(); result.Err != nil {
|
||||
if result.Err = post.IsValid(maxPostSize); result.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,7 +134,7 @@ func (s SqlPostStore) Save(post *model.Post) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Update(newPost *model.Post, oldPost *model.Post) store.StoreChannel {
|
||||
func (s *SqlPostStore) Update(newPost *model.Post, oldPost *model.Post) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
newPost.UpdateAt = model.GetMillis()
|
||||
newPost.PreCommit()
|
||||
@@ -133,7 +145,15 @@ func (s SqlPostStore) Update(newPost *model.Post, oldPost *model.Post) store.Sto
|
||||
oldPost.Id = model.NewId()
|
||||
oldPost.PreCommit()
|
||||
|
||||
if result.Err = newPost.IsValid(); result.Err != nil {
|
||||
var maxPostSize int
|
||||
if result := <-s.GetMaxPostSize(); result.Err != nil {
|
||||
result.Err = model.NewAppError("SqlPostStore.Save", "store.sql_post.update.app_error", nil, "id="+newPost.Id+", "+result.Err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else {
|
||||
maxPostSize = result.Data.(int)
|
||||
}
|
||||
|
||||
if result.Err = newPost.IsValid(maxPostSize); result.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,11 +175,19 @@ func (s SqlPostStore) Update(newPost *model.Post, oldPost *model.Post) store.Sto
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Overwrite(post *model.Post) store.StoreChannel {
|
||||
func (s *SqlPostStore) Overwrite(post *model.Post) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
post.UpdateAt = model.GetMillis()
|
||||
|
||||
if result.Err = post.IsValid(); result.Err != nil {
|
||||
var maxPostSize int
|
||||
if result := <-s.GetMaxPostSize(); result.Err != nil {
|
||||
result.Err = model.NewAppError("SqlPostStore.Save", "store.sql_post.overwrite.app_error", nil, "id="+post.Id+", "+result.Err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else {
|
||||
maxPostSize = result.Data.(int)
|
||||
}
|
||||
|
||||
if result.Err = post.IsValid(maxPostSize); result.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -171,7 +199,7 @@ func (s SqlPostStore) Overwrite(post *model.Post) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetFlaggedPosts(userId string, offset int, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetFlaggedPosts(userId string, offset int, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
pl := model.NewPostList()
|
||||
|
||||
@@ -189,7 +217,7 @@ func (s SqlPostStore) GetFlaggedPosts(userId string, offset int, limit int) stor
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
pl := model.NewPostList()
|
||||
|
||||
@@ -234,7 +262,7 @@ func (s SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int,
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetFlaggedPostsForChannel(userId, channelId string, offset int, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetFlaggedPostsForChannel(userId, channelId string, offset int, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
pl := model.NewPostList()
|
||||
|
||||
@@ -263,7 +291,7 @@ func (s SqlPostStore) GetFlaggedPostsForChannel(userId, channelId string, offset
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Get(id string) store.StoreChannel {
|
||||
func (s *SqlPostStore) Get(id string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
pl := model.NewPostList()
|
||||
|
||||
@@ -308,7 +336,7 @@ func (s SqlPostStore) Get(id string) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetSingle(id string) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetSingle(id string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var post model.Post
|
||||
err := s.GetReplica().SelectOne(&post, "SELECT * FROM Posts WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": id})
|
||||
@@ -325,12 +353,12 @@ type etagPosts struct {
|
||||
UpdateAt int64
|
||||
}
|
||||
|
||||
func (s SqlPostStore) InvalidateLastPostTimeCache(channelId string) {
|
||||
lastPostTimeCache.Remove(channelId)
|
||||
func (s *SqlPostStore) InvalidateLastPostTimeCache(channelId string) {
|
||||
s.lastPostTimeCache.Remove(channelId)
|
||||
|
||||
// Keys are "{channelid}{limit}" and caching only occurs on limits of 30 and 60
|
||||
lastPostsCache.Remove(channelId + "30")
|
||||
lastPostsCache.Remove(channelId + "60")
|
||||
s.lastPostsCache.Remove(channelId + "30")
|
||||
s.lastPostsCache.Remove(channelId + "60")
|
||||
|
||||
if s.metrics != nil {
|
||||
s.metrics.IncrementMemCacheInvalidationCounter("Last Post Time - Remove by Channel Id")
|
||||
@@ -338,10 +366,10 @@ func (s SqlPostStore) InvalidateLastPostTimeCache(channelId string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetEtag(channelId string, allowFromCache bool) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetEtag(channelId string, allowFromCache bool) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if allowFromCache {
|
||||
if cacheItem, ok := lastPostTimeCache.Get(channelId); ok {
|
||||
if cacheItem, ok := s.lastPostTimeCache.Get(channelId); ok {
|
||||
if s.metrics != nil {
|
||||
s.metrics.IncrementMemCacheHitCounter("Last Post Time")
|
||||
}
|
||||
@@ -366,11 +394,11 @@ func (s SqlPostStore) GetEtag(channelId string, allowFromCache bool) store.Store
|
||||
result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, et.UpdateAt)
|
||||
}
|
||||
|
||||
lastPostTimeCache.AddWithExpiresInSecs(channelId, et.UpdateAt, LAST_POST_TIME_CACHE_SEC)
|
||||
s.lastPostTimeCache.AddWithExpiresInSecs(channelId, et.UpdateAt, LAST_POST_TIME_CACHE_SEC)
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Delete(postId string, time int64) store.StoreChannel {
|
||||
func (s *SqlPostStore) Delete(postId string, time int64) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
_, err := s.GetMaster().Exec("Update Posts SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": postId, "RootId": postId})
|
||||
if err != nil {
|
||||
@@ -379,7 +407,7 @@ func (s SqlPostStore) Delete(postId string, time int64) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) permanentDelete(postId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) permanentDelete(postId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
_, err := s.GetMaster().Exec("DELETE FROM Posts WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"Id": postId, "RootId": postId})
|
||||
if err != nil {
|
||||
@@ -388,7 +416,7 @@ func (s SqlPostStore) permanentDelete(postId string) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) permanentDeleteAllCommentByUser(userId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) permanentDeleteAllCommentByUser(userId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
_, err := s.GetMaster().Exec("DELETE FROM Posts WHERE UserId = :UserId AND RootId != ''", map[string]interface{}{"UserId": userId})
|
||||
if err != nil {
|
||||
@@ -397,7 +425,7 @@ func (s SqlPostStore) permanentDeleteAllCommentByUser(userId string) store.Store
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) PermanentDeleteByUser(userId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) PermanentDeleteByUser(userId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
// First attempt to delete all the comments for a user
|
||||
if r := <-s.permanentDeleteAllCommentByUser(userId); r.Err != nil {
|
||||
@@ -437,7 +465,7 @@ func (s SqlPostStore) PermanentDeleteByUser(userId string) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) PermanentDeleteByChannel(channelId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) PermanentDeleteByChannel(channelId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId}); err != nil {
|
||||
result.Err = model.NewAppError("SqlPostStore.PermanentDeleteByChannel", "store.sql_post.permanent_delete_by_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
|
||||
@@ -445,7 +473,7 @@ func (s SqlPostStore) PermanentDeleteByChannel(channelId string) store.StoreChan
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPosts(channelId string, offset int, limit int, allowFromCache bool) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPosts(channelId string, offset int, limit int, allowFromCache bool) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if limit > 1000 {
|
||||
result.Err = model.NewAppError("SqlPostStore.GetLinearPosts", "store.sql_post.get_posts.app_error", nil, "channelId="+channelId, http.StatusBadRequest)
|
||||
@@ -454,7 +482,7 @@ func (s SqlPostStore) GetPosts(channelId string, offset int, limit int, allowFro
|
||||
|
||||
// Caching only occurs on limits of 30 and 60, the common limits requested by MM clients
|
||||
if allowFromCache && offset == 0 && (limit == 60 || limit == 30) {
|
||||
if cacheItem, ok := lastPostsCache.Get(fmt.Sprintf("%s%v", channelId, limit)); ok {
|
||||
if cacheItem, ok := s.lastPostsCache.Get(fmt.Sprintf("%s%v", channelId, limit)); ok {
|
||||
if s.metrics != nil {
|
||||
s.metrics.IncrementMemCacheHitCounter("Last Posts Cache")
|
||||
}
|
||||
@@ -498,7 +526,7 @@ func (s SqlPostStore) GetPosts(channelId string, offset int, limit int, allowFro
|
||||
|
||||
// Caching only occurs on limits of 30 and 60, the common limits requested by MM clients
|
||||
if offset == 0 && (limit == 60 || limit == 30) {
|
||||
lastPostsCache.AddWithExpiresInSecs(fmt.Sprintf("%s%v", channelId, limit), list, LAST_POSTS_CACHE_SEC)
|
||||
s.lastPostsCache.AddWithExpiresInSecs(fmt.Sprintf("%s%v", channelId, limit), list, LAST_POSTS_CACHE_SEC)
|
||||
}
|
||||
|
||||
result.Data = list
|
||||
@@ -506,12 +534,12 @@ func (s SqlPostStore) GetPosts(channelId string, offset int, limit int, allowFro
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsSince(channelId string, time int64, allowFromCache bool) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsSince(channelId string, time int64, allowFromCache bool) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if allowFromCache {
|
||||
// If the last post in the channel's time is less than or equal to the time we are getting posts since,
|
||||
// we can safely return no posts.
|
||||
if cacheItem, ok := lastPostTimeCache.Get(channelId); ok && cacheItem.(int64) <= time {
|
||||
if cacheItem, ok := s.lastPostTimeCache.Get(channelId); ok && cacheItem.(int64) <= time {
|
||||
if s.metrics != nil {
|
||||
s.metrics.IncrementMemCacheHitCounter("Last Post Time")
|
||||
}
|
||||
@@ -576,22 +604,22 @@ func (s SqlPostStore) GetPostsSince(channelId string, time int64, allowFromCache
|
||||
}
|
||||
}
|
||||
|
||||
lastPostTimeCache.AddWithExpiresInSecs(channelId, latestUpdate, LAST_POST_TIME_CACHE_SEC)
|
||||
s.lastPostTimeCache.AddWithExpiresInSecs(channelId, latestUpdate, LAST_POST_TIME_CACHE_SEC)
|
||||
|
||||
result.Data = list
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsBefore(channelId string, postId string, numPosts int, offset int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsBefore(channelId string, postId string, numPosts int, offset int) store.StoreChannel {
|
||||
return s.getPostsAround(channelId, postId, numPosts, offset, true)
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsAfter(channelId string, postId string, numPosts int, offset int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsAfter(channelId string, postId string, numPosts int, offset int) store.StoreChannel {
|
||||
return s.getPostsAround(channelId, postId, numPosts, offset, false)
|
||||
}
|
||||
|
||||
func (s SqlPostStore) getPostsAround(channelId string, postId string, numPosts int, offset int, before bool) store.StoreChannel {
|
||||
func (s *SqlPostStore) getPostsAround(channelId string, postId string, numPosts int, offset int, before bool) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var direction string
|
||||
var sort string
|
||||
@@ -672,7 +700,7 @@ func (s SqlPostStore) getPostsAround(channelId string, postId string, numPosts i
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) getRootPosts(channelId string, offset int, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) getRootPosts(channelId string, offset int, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var posts []*model.Post
|
||||
_, err := s.GetReplica().Select(&posts, "SELECT * FROM Posts WHERE ChannelId = :ChannelId AND DeleteAt = 0 ORDER BY CreateAt DESC LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Offset": offset, "Limit": limit})
|
||||
@@ -684,7 +712,7 @@ func (s SqlPostStore) getRootPosts(channelId string, offset int, limit int) stor
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) getParentsPosts(channelId string, offset int, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) getParentsPosts(channelId string, offset int, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var posts []*model.Post
|
||||
_, err := s.GetReplica().Select(&posts, `
|
||||
@@ -771,7 +799,7 @@ var specialSearchChar = []string{
|
||||
":",
|
||||
}
|
||||
|
||||
func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchParams) store.StoreChannel {
|
||||
func (s *SqlPostStore) Search(teamId string, userId string, params *model.SearchParams) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
queryParams := map[string]interface{}{
|
||||
"TeamId": teamId,
|
||||
@@ -945,7 +973,7 @@ func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchP
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
query :=
|
||||
`SELECT DISTINCT
|
||||
@@ -998,7 +1026,7 @@ func (s SqlPostStore) AnalyticsUserCountsWithPostsByDay(teamId string) store.Sto
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) AnalyticsPostCountsByDay(teamId string) store.StoreChannel {
|
||||
func (s *SqlPostStore) AnalyticsPostCountsByDay(teamId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
query :=
|
||||
`SELECT
|
||||
@@ -1053,7 +1081,7 @@ func (s SqlPostStore) AnalyticsPostCountsByDay(teamId string) store.StoreChannel
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) AnalyticsPostCount(teamId string, mustHaveFile bool, mustHaveHashtag bool) store.StoreChannel {
|
||||
func (s *SqlPostStore) AnalyticsPostCount(teamId string, mustHaveFile bool, mustHaveHashtag bool) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
query :=
|
||||
`SELECT
|
||||
@@ -1084,7 +1112,7 @@ func (s SqlPostStore) AnalyticsPostCount(teamId string, mustHaveFile bool, mustH
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsCreatedAt(channelId string, time int64) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsCreatedAt(channelId string, time int64) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
query := `SELECT * FROM Posts WHERE CreateAt = :CreateAt AND ChannelId = :ChannelId`
|
||||
|
||||
@@ -1099,7 +1127,7 @@ func (s SqlPostStore) GetPostsCreatedAt(channelId string, time int64) store.Stor
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsByIds(postIds []string) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsByIds(postIds []string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
keys := bytes.Buffer{}
|
||||
params := make(map[string]interface{})
|
||||
@@ -1127,7 +1155,7 @@ func (s SqlPostStore) GetPostsByIds(postIds []string) store.StoreChannel {
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetPostsBatchForIndexing(startTime int64, endTime int64, limit int) store.StoreChannel {
|
||||
func (s *SqlPostStore) GetPostsBatchForIndexing(startTime int64, endTime int64, limit int) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var posts []*model.PostForIndexing
|
||||
_, err1 := s.GetSearchReplica().Select(&posts,
|
||||
@@ -1167,7 +1195,7 @@ func (s SqlPostStore) GetPostsBatchForIndexing(startTime int64, endTime int64, l
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) PermanentDeleteBatch(endTime int64, limit int64) store.StoreChannel {
|
||||
func (s *SqlPostStore) PermanentDeleteBatch(endTime int64, limit int64) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var query string
|
||||
if s.DriverName() == "postgres" {
|
||||
@@ -1191,7 +1219,7 @@ func (s SqlPostStore) PermanentDeleteBatch(endTime int64, limit int64) store.Sto
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlPostStore) GetOldest() store.StoreChannel {
|
||||
func (s *SqlPostStore) GetOldest() store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var post model.Post
|
||||
err := s.GetReplica().SelectOne(&post, "SELECT * FROM Posts ORDER BY CreateAt LIMIT 1")
|
||||
@@ -1202,3 +1230,66 @@ func (s SqlPostStore) GetOldest() store.StoreChannel {
|
||||
result.Data = &post
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SqlPostStore) determineMaxPostSize() int {
|
||||
var maxPostSize int = model.POST_MESSAGE_MAX_RUNES_V1
|
||||
var maxPostSizeBytes int32
|
||||
|
||||
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
||||
// The Post.Message column in Postgres has historically been VARCHAR(4000), but
|
||||
// may be manually enlarged to support longer posts.
|
||||
if err := s.GetReplica().SelectOne(&maxPostSizeBytes, `
|
||||
SELECT
|
||||
COALESCE(character_maximum_length, 0)
|
||||
FROM
|
||||
information_schema.columns
|
||||
WHERE
|
||||
table_name = 'posts'
|
||||
AND column_name = 'message'
|
||||
`); err != nil {
|
||||
l4g.Error(utils.T("store.sql_post.query_max_post_size.error") + err.Error())
|
||||
}
|
||||
} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
|
||||
// The Post.Message column in MySQL has historically been TEXT, with a maximum
|
||||
// limit of 65535.
|
||||
if err := s.GetReplica().SelectOne(&maxPostSizeBytes, `
|
||||
SELECT
|
||||
COALESCE(CHARACTER_MAXIMUM_LENGTH, 0)
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
table_schema = DATABASE()
|
||||
AND table_name = 'Posts'
|
||||
AND column_name = 'Message'
|
||||
LIMIT 0, 1
|
||||
`); err != nil {
|
||||
l4g.Error(utils.T("store.sql_post.query_max_post_size.error") + err.Error())
|
||||
}
|
||||
} else {
|
||||
l4g.Warn(utils.T("store.sql_post.query_max_post_size.unrecognized_driver"))
|
||||
}
|
||||
|
||||
l4g.Trace(utils.T("store.sql_post.query_max_post_size.max_post_size_bytes"), maxPostSizeBytes)
|
||||
|
||||
// Assume a worst-case representation of four bytes per rune.
|
||||
maxPostSize = int(maxPostSizeBytes) / 4
|
||||
|
||||
// To maintain backwards compatibility, don't yield a maximum post
|
||||
// size smaller than the previous limit, even though it wasn't
|
||||
// actually possible to store 4000 runes in all cases.
|
||||
if maxPostSize < model.POST_MESSAGE_MAX_RUNES_V1 {
|
||||
maxPostSize = model.POST_MESSAGE_MAX_RUNES_V1
|
||||
}
|
||||
|
||||
return maxPostSize
|
||||
}
|
||||
|
||||
// GetMaxPostSize returns the maximum number of runes that may be stored in a post.
|
||||
func (s *SqlPostStore) GetMaxPostSize() store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
s.maxPostSizeOnce.Do(func() {
|
||||
s.maxPostSizeCached = s.determineMaxPostSize()
|
||||
})
|
||||
result.Data = s.maxPostSizeCached
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user