mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-18 18:18:23 -05:00
Force membership sync on reconnect (#35299)
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
944c345687
commit
c6d00615dd
2 changed files with 46 additions and 1 deletions
|
|
@ -88,9 +88,16 @@ func (scs *Service) HandleMembershipBatchChange(channelID string, userIDs []stri
|
|||
scs.queueMembershipSyncTask(channelID, "", "", syncMsg, nil)
|
||||
}
|
||||
|
||||
// SyncAllChannelMembers synchronizes all channel members to a specific remote.
|
||||
// SyncAllChannelMembers synchronizes channel members to a specific remote.
|
||||
// This is typically called when a channel is first shared with a remote cluster.
|
||||
// If remote is provided, it will be used instead of fetching from the database.
|
||||
//
|
||||
// When LastMembersSyncAt is non-zero, only members updated after that cursor are synced (i.e., the delta).
|
||||
// When LastMembersSyncAt is zero (initial share), all current members are synced.
|
||||
//
|
||||
// Limitation: this function only detects membership additions and modifications, not removals.
|
||||
// Channel member rows are hard-deleted from the database, so members removed while a remote was
|
||||
// offline cannot be detected by this query. Removals rely on real-time HandleMembershipChange events.
|
||||
func (scs *Service) SyncAllChannelMembers(channelID string, remoteID string, remote *model.SharedChannelRemote) error {
|
||||
if !scs.isChannelMemberSyncEnabled() {
|
||||
return nil
|
||||
|
|
@ -227,6 +234,43 @@ func (scs *Service) syncMembersInBatches(channelID, remoteID string, members mod
|
|||
return nil
|
||||
}
|
||||
|
||||
// ForceMembershipSyncForRemote syncs channel membership for all channels shared with the
|
||||
// specified remote. Called when a remote comes back online to catch up on any membership
|
||||
// changes that occurred while it was offline.
|
||||
//
|
||||
// Note: SyncAllChannelMembers uses the LastMembersSyncAt cursor on each SharedChannelRemote
|
||||
// record, so only the membership delta since the last successful sync is sent, not the full
|
||||
// member list. See SyncAllChannelMembers for known limitations regarding removed members.
|
||||
func (scs *Service) ForceMembershipSyncForRemote(rc *model.RemoteCluster) {
|
||||
if !scs.isChannelMemberSyncEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
opts := model.SharedChannelRemoteFilterOpts{
|
||||
RemoteId: rc.RemoteId,
|
||||
}
|
||||
scrs, err := scs.server.GetStore().SharedChannel().GetRemotes(0, 999999, opts)
|
||||
if err != nil {
|
||||
scs.server.Log().Log(mlog.LvlSharedChannelServiceError, "Failed to fetch shared channel remotes for membership sync",
|
||||
mlog.String("remote", rc.DisplayName),
|
||||
mlog.String("remoteId", rc.RemoteId),
|
||||
mlog.Err(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
for _, scr := range scrs {
|
||||
if syncErr := scs.SyncAllChannelMembers(scr.ChannelId, rc.RemoteId, scr); syncErr != nil {
|
||||
scs.server.Log().Log(mlog.LvlSharedChannelServiceError, "Failed to sync channel members for reconnected remote",
|
||||
mlog.String("channel_id", scr.ChannelId),
|
||||
mlog.String("remote", rc.DisplayName),
|
||||
mlog.String("remoteId", rc.RemoteId),
|
||||
mlog.Err(syncErr),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// processMembershipChange processes a channel membership change task.
|
||||
// It determines which remotes should receive the update and creates tasks for each.
|
||||
func (scs *Service) processMembershipChange(syncMsg *model.SyncMsg) {
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@ func (scs *Service) onConnectionStateChange(rc *model.RemoteCluster, online bool
|
|||
// when a previously offline remote comes back online force a sync.
|
||||
scs.SendPendingInvitesForRemote(rc)
|
||||
scs.ForceSyncForRemote(rc)
|
||||
scs.ForceMembershipSyncForRemote(rc)
|
||||
|
||||
// Schedule global user sync if feature is enabled
|
||||
scs.scheduleGlobalUserSync(rc)
|
||||
|
|
|
|||
Loading…
Reference in a new issue