MM-52600: [Shared Channels] Shared channels do not sync channel membership (#30976)

Этот коммит содержится в:
catalintomai
2025-06-15 10:07:56 +02:00
коммит произвёл GitHub
родитель 0082e3e94d
Коммит fa1c77d9b0
37 изменённых файлов: 3371 добавлений и 85 удалений

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

@@ -2070,22 +2070,34 @@ func (s SqlChannelStore) PatchMultipleMembersNotifyProps(members []*model.Channe
return updated, nil
}
func (s SqlChannelStore) GetMembers(channelID string, offset, limit int) (model.ChannelMembers, error) {
sql, args, err := s.channelMembersForTeamWithSchemeSelectQuery.
func (s SqlChannelStore) GetMembers(opts model.ChannelMembersGetOptions) (model.ChannelMembers, error) {
query := s.channelMembersForTeamWithSchemeSelectQuery.
Where(sq.Eq{
"ChannelId": channelID,
}).
Limit(uint64(limit)).
Offset(uint64(offset)).
ToSql()
"ChannelId": opts.ChannelID,
})
if opts.UpdatedAfter > 0 {
query = query.Where(sq.Gt{"ChannelMembers.LastUpdateAt": opts.UpdatedAfter})
query = query.OrderBy("ChannelMembers.LastUpdateAt")
}
if opts.Limit > 0 {
query = query.Limit(uint64(opts.Limit))
}
if opts.Offset > 0 {
query = query.Offset(uint64(opts.Offset))
}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrapf(err, "GetMember_ToSql ChannelID=%s", channelID)
return nil, errors.Wrapf(err, "GetMember_ToSql ChannelID=%s", opts.ChannelID)
}
dbMembers := channelMemberWithSchemeRolesList{}
err = s.GetReplica().Select(&dbMembers, sql, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to get ChannelMembers with channelId=%s", channelID)
return nil, errors.Wrapf(err, "failed to get ChannelMembers with channelId=%s", opts.ChannelID)
}
return dbMembers.ToModel(), nil

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

@@ -417,6 +417,7 @@ func sharedChannelRemoteFields(prefix string) []string {
"COALESCE(" + prefix + "LastPostCreateID,'') AS LastPostCreateID",
prefix + "LastPostUpdateAt",
"COALESCE(" + prefix + "LastPostId,'') AS LastPostUpdateID",
prefix + "LastMembersSyncAt",
}
}
@@ -708,6 +709,7 @@ func sharedChannelUserFields(prefix string) []string {
prefix + "RemoteId",
prefix + "CreateAt",
prefix + "LastSyncAt",
prefix + "LastMembershipSyncAt",
}
}
@@ -720,7 +722,7 @@ func (s SqlSharedChannelStore) SaveUser(scUser *model.SharedChannelUser) (*model
query, args, err := s.getQueryBuilder().Insert("SharedChannelUsers").
Columns(sharedChannelUserFields("")...).
Values(scUser.Id, scUser.UserId, scUser.ChannelId, scUser.RemoteId, scUser.CreateAt, scUser.LastSyncAt).
Values(scUser.Id, scUser.UserId, scUser.ChannelId, scUser.RemoteId, scUser.CreateAt, scUser.LastSyncAt, scUser.LastMembershipSyncAt).
ToSql()
if err != nil {
return nil, errors.Wrapf(err, "savesharedchanneluser_tosql")
@@ -853,6 +855,25 @@ func (s SqlSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID str
return nil
}
// UpdateUserLastMembershipSyncAt updates the LastMembershipSyncAt timestamp for the specified SharedChannelUser using the provided sync time.
func (s SqlSharedChannelStore) UpdateUserLastMembershipSyncAt(userID string, channelID string, remoteID string, syncTime int64) error {
query := s.getQueryBuilder().
Update("SharedChannelUsers AS scu").
Set("LastMembershipSyncAt", sq.Expr("GREATEST(scu.LastMembershipSyncAt, ?)", syncTime)).
Where(sq.Eq{
"scu.UserId": userID,
"scu.ChannelId": channelID,
"scu.RemoteId": remoteID,
})
_, err := s.GetMaster().ExecBuilder(query)
if err != nil {
return fmt.Errorf("failed to update LastMembershipSyncAt for SharedChannelUser with userId=%s, channelId=%s, remoteId=%s: %w",
userID, channelID, remoteID, err)
}
return nil
}
func sharedChannelAttachementFields(prefix string) []string {
if prefix != "" && !strings.HasSuffix(prefix, ".") {
prefix = prefix + "."

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

@@ -0,0 +1,66 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package sqlstore
import (
"database/sql"
"fmt"
"github.com/mattermost/mattermost/server/public/model"
sq "github.com/mattermost/squirrel"
"github.com/pkg/errors"
)
// UpdateRemoteMembershipCursor updates the LastMembersSyncAt timestamp for the specified SharedChannelRemote,
// but only if the new timestamp is greater than the current value.
func (s SqlSharedChannelStore) UpdateRemoteMembershipCursor(id string, syncTime int64) error {
query := s.getQueryBuilder().
Update("SharedChannelRemotes")
query = query.Set("LastMembersSyncAt", sq.Expr("GREATEST(LastMembersSyncAt, ?)", syncTime))
query = query.Where(sq.Eq{"Id": id})
result, err := s.GetMaster().ExecBuilder(query)
if err != nil {
return errors.Wrap(err, "failed to update membership cursor for SharedChannelRemote")
}
count, err := result.RowsAffected()
if err != nil {
return errors.Wrap(err, "failed to determine rows affected")
}
if count == 0 {
return fmt.Errorf("id not found: %s", id)
}
return nil
}
// GetUserChanges gets all SharedChannelUser changes for a given user, channel after a specific time.
// This is used to detect if there are conflicting membership changes.
func (s SqlSharedChannelStore) GetUserChanges(userID string, channelID string, afterTime int64) ([]*model.SharedChannelUser, error) {
squery, args, err := s.getQueryBuilder().
Select(sharedChannelUserFields("")...).
From("SharedChannelUsers").
Where(sq.Eq{"SharedChannelUsers.UserId": userID}).
Where(sq.Eq{"SharedChannelUsers.ChannelId": channelID}).
Where(sq.Gt{"SharedChannelUsers.LastSyncAt": afterTime}).
ToSql()
if err != nil {
return nil, errors.Wrapf(err, "getsharedchanneluserchanges_tosql")
}
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 changes with UserId=%s, ChannelId=%s, afterTime=%d",
userID, channelID, afterTime)
}
return users, nil
}