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 (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
"image"
|
||||
"image/gif"
|
||||
"image/jpeg"
|
||||
@@ -16,6 +14,9 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -57,6 +58,7 @@ type FileInfo struct {
|
||||
Height int `json:"height,omitempty"`
|
||||
HasPreviewImage bool `json:"has_preview_image,omitempty"`
|
||||
MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization
|
||||
Content string `json:"-"`
|
||||
}
|
||||
|
||||
func (fi *FileInfo) ToJson() string {
|
||||
|
||||
@@ -3121,6 +3121,24 @@ func (s *OpenTracingLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileI
|
||||
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) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
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) {
|
||||
|
||||
tries := 0
|
||||
|
||||
@@ -38,6 +38,7 @@ func newSqlFileInfoStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface
|
||||
table.ColMap("ThumbnailPath").SetMaxSize(512)
|
||||
table.ColMap("PreviewPath").SetMaxSize(512)
|
||||
table.ColMap("Name").SetMaxSize(256)
|
||||
table.ColMap("Content").SetMaxSize(0)
|
||||
table.ColMap("Extension").SetMaxSize(64)
|
||||
table.ColMap("MimeType").SetMaxSize(256)
|
||||
}
|
||||
@@ -272,6 +273,33 @@ func (fs SqlFileInfoStore) AttachToPost(fileId, postId, creatorId string) error
|
||||
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) {
|
||||
if _, err := fs.GetMaster().Exec(
|
||||
`UPDATE
|
||||
|
||||
@@ -192,6 +192,7 @@ func upgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error
|
||||
upgradeDatabaseToVersion528(sqlStore)
|
||||
upgradeDatabaseToVersion5281(sqlStore)
|
||||
upgradeDatabaseToVersion529(sqlStore)
|
||||
upgradeDatabaseToVersion530(sqlStore)
|
||||
|
||||
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 {
|
||||
teamsQuery, _, err := sqlStore.getQueryBuilder().Select(`COALESCE(SUM(CASE
|
||||
WHEN CHAR_LENGTH(SchemeId) > 26 THEN 1
|
||||
|
||||
@@ -569,6 +569,7 @@ type FileInfoStore interface {
|
||||
PermanentDelete(fileId string) error
|
||||
PermanentDeleteBatch(endTime int64, limit int64) (int64, error)
|
||||
PermanentDeleteByUser(userId string) (int64, error)
|
||||
SetContent(fileId, content string) error
|
||||
ClearCaches()
|
||||
}
|
||||
|
||||
|
||||
@@ -253,6 +253,20 @@ func (_m *FileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, error) {
|
||||
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
|
||||
func (_m *FileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error) {
|
||||
ret := _m.Called(info)
|
||||
|
||||
@@ -2861,6 +2861,22 @@ func (s *TimerLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, e
|
||||
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) {
|
||||
start := timemodule.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user