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
Этот коммит содержится в:
Jesús Espino
2020-11-02 15:43:48 +01:00
коммит произвёл GitHub
родитель 9bff309dd0
Коммит 24621a22ed
8 изменённых файлов: 111 добавлений и 2 удалений

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

@@ -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()