Add the content field to FileInfo (#15749)
* Add the content field to FileInfo * Fixing the upgrade code * Trying to fix the text-scheme * Fixing test-schema * Fixing test-schema * Moving the migration to the next version
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
9bff309dd0
Коммит
24621a22ed
@@ -6,8 +6,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/disintegration/imaging"
|
|
||||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
|
||||||
"image"
|
"image"
|
||||||
"image/gif"
|
"image/gif"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
@@ -16,6 +14,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -57,6 +58,7 @@ type FileInfo struct {
|
|||||||
Height int `json:"height,omitempty"`
|
Height int `json:"height,omitempty"`
|
||||||
HasPreviewImage bool `json:"has_preview_image,omitempty"`
|
HasPreviewImage bool `json:"has_preview_image,omitempty"`
|
||||||
MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization
|
MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization
|
||||||
|
Content string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fi *FileInfo) ToJson() string {
|
func (fi *FileInfo) ToJson() string {
|
||||||
|
|||||||
@@ -3121,6 +3121,24 @@ func (s *OpenTracingLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileI
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *OpenTracingLayerFileInfoStore) SetContent(fileId string, content string) error {
|
||||||
|
origCtx := s.Root.Store.Context()
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "FileInfoStore.SetContent")
|
||||||
|
s.Root.Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
s.Root.Store.SetContext(origCtx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
err := s.FileInfoStore.SetContent(fileId, content)
|
||||||
|
if err != nil {
|
||||||
|
span.LogFields(spanlog.Error(err))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
func (s *OpenTracingLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "FileInfoStore.Upsert")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "FileInfoStore.Upsert")
|
||||||
|
|||||||
@@ -3336,6 +3336,26 @@ func (s *RetryLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, e
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RetryLayerFileInfoStore) SetContent(fileId string, content string) error {
|
||||||
|
|
||||||
|
tries := 0
|
||||||
|
for {
|
||||||
|
err := s.FileInfoStore.SetContent(fileId, content)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !isRepeatableError(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tries++
|
||||||
|
if tries >= 3 {
|
||||||
|
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *RetryLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
func (s *RetryLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ func newSqlFileInfoStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface
|
|||||||
table.ColMap("ThumbnailPath").SetMaxSize(512)
|
table.ColMap("ThumbnailPath").SetMaxSize(512)
|
||||||
table.ColMap("PreviewPath").SetMaxSize(512)
|
table.ColMap("PreviewPath").SetMaxSize(512)
|
||||||
table.ColMap("Name").SetMaxSize(256)
|
table.ColMap("Name").SetMaxSize(256)
|
||||||
|
table.ColMap("Content").SetMaxSize(0)
|
||||||
table.ColMap("Extension").SetMaxSize(64)
|
table.ColMap("Extension").SetMaxSize(64)
|
||||||
table.ColMap("MimeType").SetMaxSize(256)
|
table.ColMap("MimeType").SetMaxSize(256)
|
||||||
}
|
}
|
||||||
@@ -272,6 +273,33 @@ func (fs SqlFileInfoStore) AttachToPost(fileId, postId, creatorId string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs SqlFileInfoStore) SetContent(fileId, content string) error {
|
||||||
|
query := fs.getQueryBuilder().
|
||||||
|
Update("FileInfo").
|
||||||
|
Set("Content", content).
|
||||||
|
Where(sq.Eq{"Id": fileId})
|
||||||
|
|
||||||
|
queryString, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "file_info_tosql")
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlResult, err := fs.GetMaster().Exec(queryString, args...)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to update FileInfo content with id=%s", fileId)
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := sqlResult.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
// RowsAffected should never fail with the MySQL or Postgres drivers
|
||||||
|
return errors.Wrap(err, "unable to retrieve rows affected")
|
||||||
|
} else if count == 0 {
|
||||||
|
// Could not attach the file to the post
|
||||||
|
return store.NewErrInvalidInput("FileInfo", "<id>", fmt.Sprintf("<%s>", fileId))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) DeleteForPost(postId string) (string, error) {
|
func (fs SqlFileInfoStore) DeleteForPost(postId string) (string, error) {
|
||||||
if _, err := fs.GetMaster().Exec(
|
if _, err := fs.GetMaster().Exec(
|
||||||
`UPDATE
|
`UPDATE
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ func upgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error
|
|||||||
upgradeDatabaseToVersion528(sqlStore)
|
upgradeDatabaseToVersion528(sqlStore)
|
||||||
upgradeDatabaseToVersion5281(sqlStore)
|
upgradeDatabaseToVersion5281(sqlStore)
|
||||||
upgradeDatabaseToVersion529(sqlStore)
|
upgradeDatabaseToVersion529(sqlStore)
|
||||||
|
upgradeDatabaseToVersion530(sqlStore)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -865,6 +866,15 @@ func upgradeDatabaseToVersion5281(sqlStore SqlStore) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upgradeDatabaseToVersion530(sqlStore SqlStore) {
|
||||||
|
// if shouldPerformUpgrade(sqlStore, VERSION_5_29_0, VERSION_5_30_0) {
|
||||||
|
|
||||||
|
sqlStore.CreateColumnIfNotExistsNoDefault("FileInfo", "Content", "longtext", "text")
|
||||||
|
|
||||||
|
// saveSchemaVersion(sqlStore, VERSION_5_30_0)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
func precheckMigrationToVersion528(sqlStore SqlStore) error {
|
func precheckMigrationToVersion528(sqlStore SqlStore) error {
|
||||||
teamsQuery, _, err := sqlStore.getQueryBuilder().Select(`COALESCE(SUM(CASE
|
teamsQuery, _, err := sqlStore.getQueryBuilder().Select(`COALESCE(SUM(CASE
|
||||||
WHEN CHAR_LENGTH(SchemeId) > 26 THEN 1
|
WHEN CHAR_LENGTH(SchemeId) > 26 THEN 1
|
||||||
|
|||||||
@@ -569,6 +569,7 @@ type FileInfoStore interface {
|
|||||||
PermanentDelete(fileId string) error
|
PermanentDelete(fileId string) error
|
||||||
PermanentDeleteBatch(endTime int64, limit int64) (int64, error)
|
PermanentDeleteBatch(endTime int64, limit int64) (int64, error)
|
||||||
PermanentDeleteByUser(userId string) (int64, error)
|
PermanentDeleteByUser(userId string) (int64, error)
|
||||||
|
SetContent(fileId, content string) error
|
||||||
ClearCaches()
|
ClearCaches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -253,6 +253,20 @@ func (_m *FileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, error) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetContent provides a mock function with given fields: fileId, content
|
||||||
|
func (_m *FileInfoStore) SetContent(fileId string, content string) error {
|
||||||
|
ret := _m.Called(fileId, content)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||||
|
r0 = rf(fileId, content)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// Upsert provides a mock function with given fields: info
|
// Upsert provides a mock function with given fields: info
|
||||||
func (_m *FileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
func (_m *FileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
||||||
ret := _m.Called(info)
|
ret := _m.Called(info)
|
||||||
|
|||||||
@@ -2861,6 +2861,22 @@ func (s *TimerLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, e
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerFileInfoStore) SetContent(fileId string, content string) error {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
err := s.FileInfoStore.SetContent(fileId, content)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if err == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("FileInfoStore.SetContent", success, elapsed)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
func (s *TimerLayerFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user