[GH-18504] Migrate from gorp to sqlx in store/sqlstore/file_info_store.go (#18637)
* Migrate from gorp to sqlx in store/sqlstore/file_info_store.go Signed-off-by: Igor German <germanenak@gmail.com> * Use separate structs for FileInfo Signed-off-by: Igor German <germanenak@gmail.com> * Fix CR comments Signed-off-by: Igor German <germanenak@gmail.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
@@ -19,6 +19,54 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/v6/store"
|
"github.com/mattermost/mattermost-server/v6/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type fileInfoWithChannelID struct {
|
||||||
|
Id string
|
||||||
|
CreatorId string
|
||||||
|
PostId string
|
||||||
|
ChannelId string
|
||||||
|
CreateAt int64
|
||||||
|
UpdateAt int64
|
||||||
|
DeleteAt int64
|
||||||
|
Path string
|
||||||
|
ThumbnailPath string
|
||||||
|
PreviewPath string
|
||||||
|
Name string
|
||||||
|
Extension string
|
||||||
|
Size int64
|
||||||
|
MimeType string
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
HasPreviewImage bool
|
||||||
|
MiniPreview *[]byte
|
||||||
|
Content string
|
||||||
|
RemoteId *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi fileInfoWithChannelID) ToModel() *model.FileInfo {
|
||||||
|
return &model.FileInfo{
|
||||||
|
Id: fi.Id,
|
||||||
|
CreatorId: fi.CreatorId,
|
||||||
|
PostId: fi.PostId,
|
||||||
|
ChannelId: fi.ChannelId,
|
||||||
|
CreateAt: fi.CreateAt,
|
||||||
|
UpdateAt: fi.UpdateAt,
|
||||||
|
DeleteAt: fi.DeleteAt,
|
||||||
|
Path: fi.Path,
|
||||||
|
ThumbnailPath: fi.ThumbnailPath,
|
||||||
|
PreviewPath: fi.PreviewPath,
|
||||||
|
Name: fi.Name,
|
||||||
|
Extension: fi.Extension,
|
||||||
|
Size: fi.Size,
|
||||||
|
MimeType: fi.MimeType,
|
||||||
|
Width: fi.Width,
|
||||||
|
Height: fi.Height,
|
||||||
|
HasPreviewImage: fi.HasPreviewImage,
|
||||||
|
MiniPreview: fi.MiniPreview,
|
||||||
|
Content: fi.Content,
|
||||||
|
RemoteId: fi.RemoteId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type SqlFileInfoStore struct {
|
type SqlFileInfoStore struct {
|
||||||
*SqlStore
|
*SqlStore
|
||||||
metrics einterfaces.MetricsInterface
|
metrics einterfaces.MetricsInterface
|
||||||
@@ -93,7 +141,16 @@ func (fs SqlFileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fs.GetMaster().Insert(info); err != nil {
|
query := `
|
||||||
|
INSERT INTO FileInfo
|
||||||
|
(Id, CreatorId, PostId, CreateAt, UpdateAt, DeleteAt, Path, ThumbnailPath, PreviewPath,
|
||||||
|
Name, Extension, Size, MimeType, Width, Height, HasPreviewImage, MiniPreview, Content, RemoteId)
|
||||||
|
VALUES
|
||||||
|
(:Id, :CreatorId, :PostId, :CreateAt, :UpdateAt, :DeleteAt, :Path, :ThumbnailPath, :PreviewPath,
|
||||||
|
:Name, :Extension, :Size, :MimeType, :Width, :Height, :HasPreviewImage, :MiniPreview, :Content, :RemoteId)
|
||||||
|
`
|
||||||
|
|
||||||
|
if _, err := fs.GetMasterX().NamedExec(query, info); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to save FileInfo")
|
return nil, errors.Wrap(err, "failed to save FileInfo")
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
@@ -113,10 +170,18 @@ func (fs SqlFileInfoStore) GetByIds(ids []string) ([]*model.FileInfo, error) {
|
|||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
var infos []*model.FileInfo
|
items := []fileInfoWithChannelID{}
|
||||||
if _, err := fs.GetReplica().Select(&infos, queryString, args...); err != nil {
|
if err := fs.GetReplicaX().Select(&items, queryString, args...); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find FileInfos")
|
return nil, errors.Wrap(err, "failed to find FileInfos")
|
||||||
}
|
}
|
||||||
|
if len(items) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
infos := make([]*model.FileInfo, 0, len(items))
|
||||||
|
for _, item := range items {
|
||||||
|
infos = append(infos, item.ToModel())
|
||||||
|
}
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,14 +191,41 @@ func (fs SqlFileInfoStore) Upsert(info *model.FileInfo) (*model.FileInfo, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := fs.GetMaster().Update(info)
|
queryString, args, err := fs.getQueryBuilder().
|
||||||
|
Update("FileInfo").
|
||||||
|
SetMap(map[string]interface{}{
|
||||||
|
"UpdateAt": info.UpdateAt,
|
||||||
|
"DeleteAt": info.DeleteAt,
|
||||||
|
"Path": info.Path,
|
||||||
|
"ThumbnailPath": info.ThumbnailPath,
|
||||||
|
"PreviewPath": info.PreviewPath,
|
||||||
|
"Name": info.Name,
|
||||||
|
"Extension": info.Extension,
|
||||||
|
"Size": info.Size,
|
||||||
|
"MimeType": info.MimeType,
|
||||||
|
"Width": info.Width,
|
||||||
|
"Height": info.Height,
|
||||||
|
"HasPreviewImage": info.HasPreviewImage,
|
||||||
|
"Content": info.Content,
|
||||||
|
"RemoteId": info.RemoteId,
|
||||||
|
}).
|
||||||
|
Where(sq.Eq{"Id": info.Id}).
|
||||||
|
ToSql()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlResult, err := fs.GetMasterX().Exec(queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to update FileInfo")
|
return nil, errors.Wrap(err, "failed to update FileInfo")
|
||||||
}
|
}
|
||||||
if n == 0 {
|
count, err := sqlResult.RowsAffected()
|
||||||
if err = fs.GetMaster().Insert(info); err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to save FileInfo")
|
return nil, errors.Wrap(err, "unable to retrieve rows affected")
|
||||||
}
|
}
|
||||||
|
if count == 0 {
|
||||||
|
return fs.Save(info)
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
@@ -152,12 +244,12 @@ func (fs SqlFileInfoStore) get(id string, fromMaster bool) (*model.FileInfo, err
|
|||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
db := fs.GetReplica()
|
db := fs.GetReplicaX()
|
||||||
if fromMaster {
|
if fromMaster {
|
||||||
db = fs.GetMaster()
|
db = fs.GetMasterX()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.SelectOne(info, queryString, args...); err != nil {
|
if err := db.Get(info, queryString, args...); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, store.NewErrNotFound("FileInfo", id)
|
return nil, store.NewErrNotFound("FileInfo", id)
|
||||||
}
|
}
|
||||||
@@ -234,8 +326,8 @@ func (fs SqlFileInfoStore) GetWithOptions(page, perPage int, opt *model.GetFileI
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
var infos []*model.FileInfo
|
infos := []*model.FileInfo{}
|
||||||
if _, err := fs.GetReplica().Select(&infos, queryString, args...); err != nil {
|
if err := fs.GetReplicaX().Select(&infos, queryString, args...); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find FileInfos")
|
return nil, errors.Wrap(err, "failed to find FileInfos")
|
||||||
}
|
}
|
||||||
return infos, nil
|
return infos, nil
|
||||||
@@ -256,7 +348,7 @@ func (fs SqlFileInfoStore) GetByPath(path string) (*model.FileInfo, error) {
|
|||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fs.GetReplica().SelectOne(info, queryString, args...); err != nil {
|
if err := fs.GetReplicaX().Get(info, queryString, args...); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, store.NewErrNotFound("FileInfo", fmt.Sprintf("path=%s", path))
|
return nil, store.NewErrNotFound("FileInfo", fmt.Sprintf("path=%s", path))
|
||||||
}
|
}
|
||||||
@@ -270,12 +362,12 @@ func (fs SqlFileInfoStore) InvalidateFileInfosForPostCache(postId string, delete
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) GetForPost(postId string, readFromMaster, includeDeleted, allowFromCache bool) ([]*model.FileInfo, error) {
|
func (fs SqlFileInfoStore) GetForPost(postId string, readFromMaster, includeDeleted, allowFromCache bool) ([]*model.FileInfo, error) {
|
||||||
var infos []*model.FileInfo
|
infos := []*model.FileInfo{}
|
||||||
|
|
||||||
dbmap := fs.GetReplica()
|
dbmap := fs.GetReplicaX()
|
||||||
|
|
||||||
if readFromMaster {
|
if readFromMaster {
|
||||||
dbmap = fs.GetMaster()
|
dbmap = fs.GetMasterX()
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fs.getQueryBuilder().
|
query := fs.getQueryBuilder().
|
||||||
@@ -293,16 +385,14 @@ func (fs SqlFileInfoStore) GetForPost(postId string, readFromMaster, includeDele
|
|||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := dbmap.Select(&infos, queryString, args...); err != nil {
|
if err := dbmap.Select(&infos, queryString, args...); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to find FileInfos with postId=%s", postId)
|
return nil, errors.Wrapf(err, "failed to find FileInfos with postId=%s", postId)
|
||||||
}
|
}
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) GetForUser(userId string) ([]*model.FileInfo, error) {
|
func (fs SqlFileInfoStore) GetForUser(userId string) ([]*model.FileInfo, error) {
|
||||||
var infos []*model.FileInfo
|
infos := []*model.FileInfo{}
|
||||||
|
|
||||||
dbmap := fs.GetReplica()
|
|
||||||
|
|
||||||
query := fs.getQueryBuilder().
|
query := fs.getQueryBuilder().
|
||||||
Select(fs.queryFields...).
|
Select(fs.queryFields...).
|
||||||
@@ -316,27 +406,30 @@ func (fs SqlFileInfoStore) GetForUser(userId string) ([]*model.FileInfo, error)
|
|||||||
return nil, errors.Wrap(err, "file_info_tosql")
|
return nil, errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := dbmap.Select(&infos, queryString, args...); err != nil {
|
if err := fs.GetReplicaX().Select(&infos, queryString, args...); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to find FileInfos with creatorId=%s", userId)
|
return nil, errors.Wrapf(err, "failed to find FileInfos with creatorId=%s", userId)
|
||||||
}
|
}
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) AttachToPost(fileId, postId, creatorId string) error {
|
func (fs SqlFileInfoStore) AttachToPost(fileId, postId, creatorId string) error {
|
||||||
sqlResult, err := fs.GetMaster().Exec(`
|
query := fs.getQueryBuilder().
|
||||||
UPDATE
|
Update("FileInfo").
|
||||||
FileInfo
|
Set("PostId", postId).
|
||||||
SET
|
Where(sq.And{
|
||||||
PostId = :PostId
|
sq.Eq{"Id": fileId},
|
||||||
WHERE
|
sq.Eq{"PostId": ""},
|
||||||
Id = :Id
|
sq.Or{
|
||||||
AND PostId = ''
|
sq.Eq{"CreatorId": creatorId},
|
||||||
AND (CreatorId = :CreatorId OR CreatorId = 'nouser')
|
sq.Eq{"CreatorId": "nouser"},
|
||||||
`, map[string]interface{}{
|
},
|
||||||
"PostId": postId,
|
})
|
||||||
"Id": fileId,
|
|
||||||
"CreatorId": creatorId,
|
queryString, args, err := query.ToSql()
|
||||||
})
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "file_info_tosql")
|
||||||
|
}
|
||||||
|
sqlResult, err := fs.GetMasterX().Exec(queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to update FileInfo with id=%s and postId=%s", fileId, postId)
|
return errors.Wrapf(err, "failed to update FileInfo with id=%s and postId=%s", fileId, postId)
|
||||||
}
|
}
|
||||||
@@ -363,7 +456,7 @@ func (fs SqlFileInfoStore) SetContent(fileId, content string) error {
|
|||||||
return errors.Wrap(err, "file_info_tosql")
|
return errors.Wrap(err, "file_info_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fs.GetMaster().Exec(queryString, args...)
|
_, err = fs.GetMasterX().Exec(queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to update FileInfo content with id=%s", fileId)
|
return errors.Wrapf(err, "failed to update FileInfo content with id=%s", fileId)
|
||||||
}
|
}
|
||||||
@@ -372,24 +465,20 @@ func (fs SqlFileInfoStore) SetContent(fileId, content string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) DeleteForPost(postId string) (string, error) {
|
func (fs SqlFileInfoStore) DeleteForPost(postId string) (string, error) {
|
||||||
if _, err := fs.GetMaster().Exec(
|
if _, err := fs.GetMasterX().Exec(
|
||||||
`UPDATE
|
`UPDATE
|
||||||
FileInfo
|
FileInfo
|
||||||
SET
|
SET
|
||||||
DeleteAt = :DeleteAt
|
DeleteAt = ?
|
||||||
WHERE
|
WHERE
|
||||||
PostId = :PostId`, map[string]interface{}{"DeleteAt": model.GetMillis(), "PostId": postId}); err != nil {
|
PostId = ?`, model.GetMillis(), postId); err != nil {
|
||||||
return "", errors.Wrapf(err, "failed to update FileInfo with postId=%s", postId)
|
return "", errors.Wrapf(err, "failed to update FileInfo with postId=%s", postId)
|
||||||
}
|
}
|
||||||
return postId, nil
|
return postId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) PermanentDelete(fileId string) error {
|
func (fs SqlFileInfoStore) PermanentDelete(fileId string) error {
|
||||||
if _, err := fs.GetMaster().Exec(
|
if _, err := fs.GetMasterX().Exec(`DELETE FROM FileInfo WHERE Id = ?`, fileId); err != nil {
|
||||||
`DELETE FROM
|
|
||||||
FileInfo
|
|
||||||
WHERE
|
|
||||||
Id = :FileId`, map[string]interface{}{"FileId": fileId}); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to delete FileInfo with id=%s", fileId)
|
return errors.Wrapf(err, "failed to delete FileInfo with id=%s", fileId)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -398,12 +487,12 @@ func (fs SqlFileInfoStore) PermanentDelete(fileId string) error {
|
|||||||
func (fs SqlFileInfoStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) {
|
func (fs SqlFileInfoStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) {
|
||||||
var query string
|
var query string
|
||||||
if fs.DriverName() == "postgres" {
|
if fs.DriverName() == "postgres" {
|
||||||
query = "DELETE from FileInfo WHERE Id = any (array (SELECT Id FROM FileInfo WHERE CreateAt < :EndTime LIMIT :Limit))"
|
query = "DELETE from FileInfo WHERE Id = any (array (SELECT Id FROM FileInfo WHERE CreateAt < ? LIMIT ?))"
|
||||||
} else {
|
} else {
|
||||||
query = "DELETE from FileInfo WHERE CreateAt < :EndTime LIMIT :Limit"
|
query = "DELETE from FileInfo WHERE CreateAt < ? LIMIT ?"
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlResult, err := fs.GetMaster().Exec(query, map[string]interface{}{"EndTime": endTime, "Limit": limit})
|
sqlResult, err := fs.GetMasterX().Exec(query, endTime, limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "failed to delete FileInfos in batch")
|
return 0, errors.Wrap(err, "failed to delete FileInfos in batch")
|
||||||
}
|
}
|
||||||
@@ -417,9 +506,9 @@ func (fs SqlFileInfoStore) PermanentDeleteBatch(endTime int64, limit int64) (int
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) PermanentDeleteByUser(userId string) (int64, error) {
|
func (fs SqlFileInfoStore) PermanentDeleteByUser(userId string) (int64, error) {
|
||||||
query := "DELETE from FileInfo WHERE CreatorId = :CreatorId"
|
query := "DELETE from FileInfo WHERE CreatorId = ?"
|
||||||
|
|
||||||
sqlResult, err := fs.GetMaster().Exec(query, map[string]interface{}{"CreatorId": userId})
|
sqlResult, err := fs.GetMasterX().Exec(query, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrapf(err, "failed to delete FileInfo with creatorId=%s", userId)
|
return 0, errors.Wrapf(err, "failed to delete FileInfo with creatorId=%s", userId)
|
||||||
}
|
}
|
||||||
@@ -591,15 +680,17 @@ func (fs SqlFileInfoStore) Search(paramsList []*model.SearchParams, userId, team
|
|||||||
}
|
}
|
||||||
|
|
||||||
list := model.NewFileInfoList()
|
list := model.NewFileInfoList()
|
||||||
fileInfos := []*model.FileInfo{}
|
|
||||||
_, err = fs.GetSearchReplica().Select(&fileInfos, queryString, args...)
|
items := []fileInfoWithChannelID{}
|
||||||
|
err = fs.GetSearchReplicaX().Select(&items, queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Warn("Query error searching files.", mlog.Err(err))
|
mlog.Warn("Query error searching files.", mlog.Err(err))
|
||||||
// Don't return the error to the caller as it is of no use to the user. Instead return an empty set of search results.
|
// Don't return the error to the caller as it is of no use to the user. Instead return an empty set of search results.
|
||||||
} else {
|
} else {
|
||||||
for _, f := range fileInfos {
|
for _, item := range items {
|
||||||
list.AddFileInfo(f)
|
info := item.ToModel()
|
||||||
list.AddOrder(f.Id)
|
list.AddFileInfo(info)
|
||||||
|
list.AddOrder(info.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.MakeNonNil()
|
list.MakeNonNil()
|
||||||
@@ -617,7 +708,8 @@ func (fs SqlFileInfoStore) CountAll() (int64, error) {
|
|||||||
return int64(0), errors.Wrap(err, "count_tosql")
|
return int64(0), errors.Wrap(err, "count_tosql")
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := fs.GetReplica().SelectInt(queryString, args...)
|
var count int64
|
||||||
|
err = fs.GetReplicaX().Get(&count, queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return int64(0), errors.Wrap(err, "failed to count Files")
|
return int64(0), errors.Wrap(err, "failed to count Files")
|
||||||
}
|
}
|
||||||
@@ -625,7 +717,7 @@ func (fs SqlFileInfoStore) CountAll() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs SqlFileInfoStore) GetFilesBatchForIndexing(startTime, endTime int64, limit int) ([]*model.FileForIndexing, error) {
|
func (fs SqlFileInfoStore) GetFilesBatchForIndexing(startTime, endTime int64, limit int) ([]*model.FileForIndexing, error) {
|
||||||
var files []*model.FileForIndexing
|
files := []*model.FileForIndexing{}
|
||||||
sql, args, _ := fs.getQueryBuilder().
|
sql, args, _ := fs.getQueryBuilder().
|
||||||
Select(append(fs.queryFields, "Coalesce(p.ChannelId, '') AS ChannelId")...).
|
Select(append(fs.queryFields, "Coalesce(p.ChannelId, '') AS ChannelId")...).
|
||||||
From("FileInfo").
|
From("FileInfo").
|
||||||
@@ -635,7 +727,7 @@ func (fs SqlFileInfoStore) GetFilesBatchForIndexing(startTime, endTime int64, li
|
|||||||
OrderBy("FileInfo.CreateAt").
|
OrderBy("FileInfo.CreateAt").
|
||||||
Limit(uint64(limit)).
|
Limit(uint64(limit)).
|
||||||
ToSql()
|
ToSql()
|
||||||
_, err := fs.GetSearchReplica().Select(&files, sql, args...)
|
err := fs.GetSearchReplicaX().Select(&files, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find Files")
|
return nil, errors.Wrap(err, "failed to find Files")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -454,6 +454,22 @@ func (ss *SqlStore) GetSearchReplica() *gorp.DbMap {
|
|||||||
return ss.searchReplicas[rrNum]
|
return ss.searchReplicas[rrNum]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ss *SqlStore) GetSearchReplicaX() *sqlxDBWrapper {
|
||||||
|
ss.licenseMutex.RLock()
|
||||||
|
license := ss.license
|
||||||
|
ss.licenseMutex.RUnlock()
|
||||||
|
if license == nil {
|
||||||
|
return ss.GetMasterX()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ss.settings.DataSourceSearchReplicas) == 0 {
|
||||||
|
return ss.GetReplicaX()
|
||||||
|
}
|
||||||
|
|
||||||
|
rrNum := atomic.AddInt64(&ss.srCounter, 1) % int64(len(ss.searchReplicaXs))
|
||||||
|
return ss.searchReplicaXs[rrNum]
|
||||||
|
}
|
||||||
|
|
||||||
func (ss *SqlStore) GetReplica() *gorp.DbMap {
|
func (ss *SqlStore) GetReplica() *gorp.DbMap {
|
||||||
ss.licenseMutex.RLock()
|
ss.licenseMutex.RLock()
|
||||||
license := ss.license
|
license := ss.license
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user