MM-35133 trigger sync user immediately after change (#17579)

- ensure changes to user profile sync immediately
- refactor sync send
Этот коммит содержится в:
Doug Lauder
2021-05-20 12:07:40 -04:00
коммит произвёл GitHub
родитель 36dd0005d2
Коммит 2b02b03497
31 изменённых файлов: 1591 добавлений и 914 удалений

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

@@ -1004,26 +1004,16 @@ func (s *SqlPostStore) HasAutoResponsePostByUserSince(options model.GetPostsSinc
return exist > 0, nil
}
func (s *SqlPostStore) GetPostsSinceForSync(options model.GetPostsSinceForSyncOptions, _ /* allowFromCache */ bool) ([]*model.Post, error) {
if options.Limit < 0 || options.Limit > 1000 {
return nil, store.NewErrInvalidInput("Post", "<options.Limit>", options.Limit)
}
order := " ASC"
if options.SortDescending {
order = " DESC"
}
func (s *SqlPostStore) GetPostsSinceForSync(options model.GetPostsSinceForSyncOptions, cursor model.GetPostsSinceForSyncCursor, limit int) ([]*model.Post, model.GetPostsSinceForSyncCursor, error) {
query := s.getQueryBuilder().
Select("*").
From("Posts").
Where(sq.GtOrEq{"UpdateAt": options.Since}).
Where(sq.Eq{"ChannelId": options.ChannelId}).
Limit(uint64(options.Limit)).
OrderBy("CreateAt"+order, "DeleteAt", "Id")
Where(sq.Or{sq.Gt{"UpdateAt": cursor.LastPostUpdateAt}, sq.And{sq.Eq{"UpdateAt": cursor.LastPostUpdateAt}, sq.Gt{"Id": cursor.LastPostId}}}).
OrderBy("UpdateAt", "Id").
Limit(uint64(limit))
if options.Until > 0 {
query = query.Where(sq.LtOrEq{"UpdateAt": options.Until})
if options.ChannelId != "" {
query = query.Where(sq.Eq{"ChannelId": options.ChannelId})
}
if !options.IncludeDeleted {
@@ -1034,24 +1024,22 @@ func (s *SqlPostStore) GetPostsSinceForSync(options model.GetPostsSinceForSyncOp
query = query.Where(sq.NotEq{"COALESCE(Posts.RemoteId,'')": options.ExcludeRemoteId})
}
if options.Offset > 0 {
query = query.Offset(uint64(options.Offset))
}
queryString, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "getpostssinceforsync_tosql")
return nil, cursor, errors.Wrap(err, "getpostssinceforsync_tosql")
}
var posts []*model.Post
_, err = s.GetReplica().Select(&posts, queryString, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to find Posts with channelId=%s", options.ChannelId)
return nil, cursor, errors.Wrapf(err, "error getting Posts with channelId=%s", options.ChannelId)
}
return posts, nil
if len(posts) != 0 {
cursor.LastPostUpdateAt = posts[len(posts)-1].UpdateAt
cursor.LastPostId = posts[len(posts)-1].Id
}
return posts, cursor, nil
}
func (s *SqlPostStore) GetPostsBefore(options model.GetPostsOptions) (*model.PostList, error) {

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

@@ -14,6 +14,10 @@ import (
"github.com/pkg/errors"
)
const (
DefaultGetUsersForSyncLimit = 100
)
type SqlSharedChannelStore struct {
*SqlStore
}
@@ -40,6 +44,7 @@ func newSqlSharedChannelStore(sqlStore *SqlStore) store.SharedChannelStore {
tableSharedChannelRemotes.ColMap("ChannelId").SetMaxSize(26)
tableSharedChannelRemotes.ColMap("CreatorId").SetMaxSize(26)
tableSharedChannelRemotes.ColMap("RemoteId").SetMaxSize(26)
tableSharedChannelRemotes.ColMap("LastPostId").SetMaxSize(26)
tableSharedChannelRemotes.SetUniqueTogether("ChannelId", "RemoteId")
tableSharedChannelUsers := db.AddTableWithName(model.SharedChannelUser{}, "SharedChannelUsers").SetKeys(false, "Id")
@@ -467,20 +472,21 @@ func (s SqlSharedChannelStore) GetRemoteForUser(remoteId string, userId string)
return &rc, nil
}
// UpdateRemoteNextSyncAt updates the NextSyncAt timestamp for the specified SharedChannelRemote.
func (s SqlSharedChannelStore) UpdateRemoteNextSyncAt(id string, syncTime int64) error {
// UpdateRemoteCursor updates the LastPostUpdateAt timestamp and LastPostId for the specified SharedChannelRemote.
func (s SqlSharedChannelStore) UpdateRemoteCursor(id string, cursor model.GetPostsSinceForSyncCursor) error {
squery, args, err := s.getQueryBuilder().
Update("SharedChannelRemotes").
Set("NextSyncAt", syncTime).
Set("LastPostUpdateAt", cursor.LastPostUpdateAt).
Set("LastPostId", cursor.LastPostId).
Where(sq.Eq{"Id": id}).
ToSql()
if err != nil {
return errors.Wrap(err, "update_shared_channel_remote_next_sync_at_tosql")
return errors.Wrap(err, "update_shared_channel_remote_cursor_tosql")
}
result, err := s.GetMaster().Exec(squery, args...)
if err != nil {
return errors.Wrap(err, "failed to update NextSyncAt for SharedChannelRemote")
return errors.Wrap(err, "failed to update cursor for SharedChannelRemote")
}
count, err := result.RowsAffected()
@@ -556,8 +562,8 @@ func (s SqlSharedChannelStore) SaveUser(scUser *model.SharedChannelUser) (*model
return scUser, nil
}
// GetUser fetches a shared channel user based on user_id and remoteId.
func (s SqlSharedChannelStore) GetUser(userID string, channelID string, remoteID string) (*model.SharedChannelUser, error) {
// GetSingleUser fetches a shared channel user based on userID, channelID and remoteID.
func (s SqlSharedChannelStore) GetSingleUser(userID string, channelID string, remoteID string) (*model.SharedChannelUser, error) {
var scu model.SharedChannelUser
squery, args, err := s.getQueryBuilder().
@@ -569,7 +575,7 @@ func (s SqlSharedChannelStore) GetUser(userID string, channelID string, remoteID
ToSql()
if err != nil {
return nil, errors.Wrapf(err, "getsharedchanneluser_tosql")
return nil, errors.Wrapf(err, "getsharedchannelsingleuser_tosql")
}
if err := s.GetReplica().SelectOne(&scu, squery, args...); err != nil {
@@ -581,20 +587,104 @@ func (s SqlSharedChannelStore) GetUser(userID string, channelID string, remoteID
return &scu, nil
}
// UpdateUserLastSyncAt updates the LastSyncAt timestamp for the specified SharedChannelUser.
func (s SqlSharedChannelStore) UpdateUserLastSyncAt(id string, syncTime int64) error {
// GetUsersForUser fetches all shared channel user records based on userID.
func (s SqlSharedChannelStore) GetUsersForUser(userID string) ([]*model.SharedChannelUser, error) {
squery, args, err := s.getQueryBuilder().
Update("SharedChannelUsers").
Set("LastSyncAt", syncTime).
Where(sq.Eq{"Id": id}).
Select("*").
From("SharedChannelUsers").
Where(sq.Eq{"SharedChannelUsers.UserId": userID}).
ToSql()
if err != nil {
return errors.Wrap(err, "update_shared_channel_user_last_sync_at_tosql")
return nil, errors.Wrapf(err, "getsharedchanneluser_tosql")
}
result, err := s.GetMaster().Exec(squery, args...)
var users []*model.SharedChannelUser
if _, err := s.GetReplica().Select(&users, squery, args...); err != nil {
if err == sql.ErrNoRows {
return make([]*model.SharedChannelUser, 0), nil
}
return nil, errors.Wrapf(err, "failed to find shared channel user with UserId=%s", userID)
}
return users, nil
}
// GetUsersForSync fetches all shared channel users that need to be synchronized, meaning their
// `SharedChannelUsers.LastSyncAt` is less than or equal to `User.UpdateAt`.
func (s SqlSharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error) {
if filter.Limit <= 0 {
filter.Limit = DefaultGetUsersForSyncLimit
}
query := s.getQueryBuilder().
Select("u.*").
Distinct().
From("Users AS u").
Join("SharedChannelUsers AS scu ON u.Id = scu.UserId").
OrderBy("u.Id").
Limit(filter.Limit)
if filter.CheckProfileImage {
query = query.Where("scu.LastSyncAt < u.LastPictureUpdate")
} else {
query = query.Where("scu.LastSyncAt < u.UpdateAt")
}
if filter.ChannelID != "" {
query = query.Where(sq.Eq{"scu.ChannelId": filter.ChannelID})
}
sqlQuery, args, err := query.ToSql()
if err != nil {
return errors.Wrap(err, "failed to update LastSycnAt for SharedChannelUser")
return nil, errors.Wrapf(err, "getsharedchannelusersforsync_tosql")
}
var users []*model.User
if _, err := s.GetReplica().Select(&users, sqlQuery, args...); err != nil {
if err == sql.ErrNoRows {
return make([]*model.User, 0), nil
}
return nil, errors.Wrapf(err, "failed to fetch shared channel users with ChannelId=%s",
filter.ChannelID)
}
return users, nil
}
// UpdateUserLastSyncAt updates the LastSyncAt timestamp for the specified SharedChannelUser.
func (s SqlSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error {
args := map[string]interface{}{"UserId": userID, "ChannelId": channelID, "RemoteId": remoteID}
var query string
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
query = `
UPDATE
SharedChannelUsers AS scu
SET
LastSyncAt = GREATEST(Users.UpdateAt, Users.LastPictureUpdate)
FROM
Users
WHERE
Users.Id = scu.UserId AND scu.UserId = :UserId AND scu.ChannelId = :ChannelId AND scu.RemoteId = :RemoteId
`
} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
query = `
UPDATE
SharedChannelUsers AS scu
INNER JOIN
Users ON scu.UserId = Users.Id
SET
LastSyncAt = GREATEST(Users.UpdateAt, Users.LastPictureUpdate)
WHERE
scu.UserId = :UserId AND scu.ChannelId = :ChannelId AND scu.RemoteId = :RemoteId
`
} else {
return errors.New("unsupported DB driver " + s.DriverName())
}
result, err := s.GetMaster().Exec(query, args)
if err != nil {
return fmt.Errorf("failed to update LastSyncAt for SharedChannelUser with userId=%s, channelId=%s, remoteId=%s: %w",
userID, channelID, remoteID, err)
}
count, err := result.RowsAffected()
@@ -602,7 +692,7 @@ func (s SqlSharedChannelStore) UpdateUserLastSyncAt(id string, syncTime int64) e
return errors.Wrap(err, "failed to determine rows affected")
}
if count == 0 {
return fmt.Errorf("id not found: %s", id)
return fmt.Errorf("SharedChannelUser not found: userId=%s, channelId=%s, remoteId=%s", userID, channelID, remoteID)
}
return nil
}

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

@@ -1067,6 +1067,8 @@ func upgradeDatabaseToVersion536(sqlStore *SqlStore) {
//if shouldPerformUpgrade(sqlStore, Version5350, Version5360) {
sqlStore.CreateColumnIfNotExists("SharedChannelUsers", "ChannelId", "VARCHAR(26)", "VARCHAR(26)", "")
sqlStore.CreateColumnIfNotExists("SharedChannelRemotes", "LastPostUpdateAt", "bigint", "bigint", "0")
sqlStore.CreateColumnIfNotExists("SharedChannelRemotes", "LastPostId", "VARCHAR(26)", "VARCHAR(26)", "")
// timed dnd status support
sqlStore.CreateColumnIfNotExistsNoDefault("Status", "DNDEndTime", "BIGINT", "BIGINT")