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 удалений

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

@@ -2081,11 +2081,11 @@ func (s *RetryLayerChannelStore) GetMemberLastViewedAt(ctx context.Context, chan
}
func (s *RetryLayerChannelStore) GetMembers(channelID string, offset int, limit int) (model.ChannelMembers, error) {
func (s *RetryLayerChannelStore) GetMembers(opts model.ChannelMembersGetOptions) (model.ChannelMembers, error) {
tries := 0
for {
result, err := s.ChannelStore.GetMembers(channelID, offset, limit)
result, err := s.ChannelStore.GetMembers(opts)
if err == nil {
return result, nil
}
@@ -11642,6 +11642,27 @@ func (s *RetryLayerSharedChannelStore) GetSingleUser(userID string, channelID st
}
func (s *RetryLayerSharedChannelStore) GetUserChanges(userID string, channelID string, afterTime int64) ([]*model.SharedChannelUser, error) {
tries := 0
for {
result, err := s.SharedChannelStore.GetUserChanges(userID, channelID, afterTime)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerSharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error) {
tries := 0
@@ -11894,6 +11915,48 @@ func (s *RetryLayerSharedChannelStore) UpdateRemoteCursor(id string, cursor mode
}
func (s *RetryLayerSharedChannelStore) UpdateRemoteMembershipCursor(id string, syncTime int64) error {
tries := 0
for {
err := s.SharedChannelStore.UpdateRemoteMembershipCursor(id, syncTime)
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
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerSharedChannelStore) UpdateUserLastMembershipSyncAt(userID string, channelID string, remoteID string, syncTime int64) error {
tries := 0
for {
err := s.SharedChannelStore.UpdateUserLastMembershipSyncAt(userID, channelID, remoteID, syncTime)
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
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error {
tries := 0

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

@@ -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
}

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

@@ -232,7 +232,7 @@ type ChannelStore interface {
// It replaces existing fields and creates new ones which don't exist.
UpdateMemberNotifyProps(channelID, userID string, props map[string]string) (*model.ChannelMember, error)
PatchMultipleMembersNotifyProps(members []*model.ChannelMemberIdentifier, notifyProps map[string]string) ([]*model.ChannelMember, error)
GetMembers(channelID string, offset, limit int) (model.ChannelMembers, error)
GetMembers(opts model.ChannelMembersGetOptions) (model.ChannelMembers, error)
GetMember(ctx context.Context, channelID string, userID string) (*model.ChannelMember, error)
GetMemberLastViewedAt(ctx context.Context, channelID string, userID string) (int64, error)
GetChannelMembersTimezones(channelID string) ([]model.StringMap, error)
@@ -1014,6 +1014,7 @@ type SharedChannelStore interface {
GetRemoteByIds(channelID string, remoteID string) (*model.SharedChannelRemote, error)
GetRemotes(offset, limit int, opts model.SharedChannelRemoteFilterOpts) ([]*model.SharedChannelRemote, error)
UpdateRemoteCursor(id string, cursor model.GetPostsSinceForSyncCursor) error
UpdateRemoteMembershipCursor(id string, syncTime int64) error
DeleteRemote(remoteID string) (bool, error)
GetRemotesStatus(channelID string) ([]*model.SharedChannelRemoteStatus, error)
@@ -1021,7 +1022,9 @@ type SharedChannelStore interface {
GetSingleUser(userID string, channelID string, remoteID string) (*model.SharedChannelUser, error)
GetUsersForUser(userID string) ([]*model.SharedChannelUser, error)
GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error)
GetUserChanges(userID string, channelID string, afterTime int64) ([]*model.SharedChannelUser, error)
UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error
UpdateUserLastMembershipSyncAt(userID string, channelID string, remoteID string, syncTime int64) error
SaveAttachment(remote *model.SharedChannelAttachment) (*model.SharedChannelAttachment, error)
UpsertAttachment(remote *model.SharedChannelAttachment) (string, error)

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

@@ -73,6 +73,7 @@ func TestChannelStore(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore
t.Run("Save", func(t *testing.T) { testChannelStoreSave(t, rctx, ss) })
t.Run("SaveDirectChannel", func(t *testing.T) { testChannelStoreSaveDirectChannel(t, rctx, ss, s) })
t.Run("CreateDirectChannel", func(t *testing.T) { testChannelStoreCreateDirectChannel(t, rctx, ss) })
t.Run("GetMembersWithCursorPagination", func(t *testing.T) { testChannelStoreGetMembersWithCursorPagination(t, rctx, ss) })
t.Run("Update", func(t *testing.T) { testChannelStoreUpdate(t, rctx, ss) })
t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, rctx, ss) })
t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, rctx, ss, s) })
@@ -265,7 +266,7 @@ func testChannelStoreSaveDirectChannel(t *testing.T, rctx request.CTX, ss store.
_, nErr = ss.Channel().SaveDirectChannel(rctx, &o1, &m1, &m2)
require.NoError(t, nErr, "couldn't save direct channel", nErr)
members, nErr := ss.Channel().GetMembers(o1.Id, 0, 100)
members, nErr := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: o1.Id, Offset: 0, Limit: 100})
require.NoError(t, nErr)
require.Len(t, members, 2, "should have saved 2 members")
@@ -305,7 +306,7 @@ func testChannelStoreSaveDirectChannel(t *testing.T, rctx request.CTX, ss store.
_, nErr = ss.Channel().SaveDirectChannel(rctx, &o1, &m1, &m1)
require.NoError(t, nErr, "couldn't save direct channel", nErr)
members, nErr = ss.Channel().GetMembers(o1.Id, 0, 100)
members, nErr = ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: o1.Id, Offset: 0, Limit: 100})
require.NoError(t, nErr)
require.Len(t, members, 1, "should have saved just 1 member")
@@ -341,11 +342,72 @@ func testChannelStoreCreateDirectChannel(t *testing.T, rctx request.CTX, ss stor
ss.Channel().PermanentDelete(rctx, c1.Id)
}()
members, nErr := ss.Channel().GetMembers(c1.Id, 0, 100)
members, nErr := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: c1.Id, Offset: 0, Limit: 100})
require.NoError(t, nErr)
require.Len(t, members, 2, "should have saved 2 members")
}
// testChannelStoreGetMembersWithCursorPagination tests the cursor-based pagination functionality
// of the GetMembers method, using the UpdatedAfter parameter to return only members that were
// updated after a specific timestamp.
func testChannelStoreGetMembersWithCursorPagination(t *testing.T, rctx request.CTX, ss store.Store) {
// Create two users
u1 := &model.User{}
u1.Email = MakeEmail()
u1.Nickname = model.NewId()
_, err := ss.User().Save(rctx, u1)
require.NoError(t, err)
_, nErr := ss.Team().SaveMember(rctx, &model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1)
require.NoError(t, nErr)
u2 := &model.User{}
u2.Email = MakeEmail()
u2.Nickname = model.NewId()
_, err = ss.User().Save(rctx, u2)
require.NoError(t, err)
_, nErr = ss.Team().SaveMember(rctx, &model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}, -1)
require.NoError(t, nErr)
// Create direct channel between the users
c1, nErr := ss.Channel().CreateDirectChannel(rctx, u1, u2)
require.NoError(t, nErr, "couldn't create direct channel", nErr)
defer func() {
ss.Channel().PermanentDeleteMembersByChannel(rctx, c1.Id)
ss.Channel().PermanentDelete(rctx, c1.Id)
}()
// First get all members
members, nErr := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: c1.Id, Offset: 0, Limit: 100})
require.NoError(t, nErr)
require.Len(t, members, 2, "should have saved 2 members")
// Ensure members have different LastUpdateAt values by updating one of them after a short delay
time.Sleep(1 * time.Millisecond)
member := members[0]
_, err = ss.Channel().UpdateMember(rctx, &member)
require.NoError(t, err)
// Get members again after the update
members, nErr = ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: c1.Id, Offset: 0, Limit: 100})
require.NoError(t, nErr)
require.Len(t, members, 2, "should have 2 members")
// Find member with smaller LastUpdateAt
sort.Slice(members, func(i, j int) bool {
return members[i].LastUpdateAt < members[j].LastUpdateAt
})
updateTime := members[0].LastUpdateAt
// Test cursor-based pagination by querying for members updated after that timestamp
membersAfter, nErr := ss.Channel().GetMembers(model.ChannelMembersGetOptions{
ChannelID: c1.Id,
UpdatedAfter: updateTime,
Limit: 100,
})
require.NoError(t, nErr)
require.Len(t, membersAfter, 1, "should have found only 1 member created after the timestamp")
}
func testChannelStoreUpdate(t *testing.T, rctx request.CTX, ss store.Store) {
o1 := model.Channel{}
o1.TeamId = model.NewId()
@@ -7867,7 +7929,7 @@ func testChannelStoreRemoveAllDeactivatedMembers(t *testing.T, rctx request.CTX,
require.NoError(t, err)
// Get all the channel members. Check there are 3.
d1, err := ss.Channel().GetMembers(c1.Id, 0, 1000)
d1, err := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: c1.Id, Offset: 0, Limit: 1000})
assert.NoError(t, err)
assert.Len(t, d1, 3)
@@ -7887,7 +7949,7 @@ func testChannelStoreRemoveAllDeactivatedMembers(t *testing.T, rctx request.CTX,
assert.NoError(t, ss.Channel().RemoveAllDeactivatedMembers(rctx, c1.Id))
// Get all the channel members. Check there is now only 1: m3.
d2, err := ss.Channel().GetMembers(c1.Id, 0, 1000)
d2, err := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: c1.Id, Offset: 0, Limit: 1000})
assert.NoError(t, err)
assert.Len(t, d2, 1)
assert.Equal(t, u3.Id, d2[0].UserId)

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

@@ -5340,7 +5340,7 @@ func groupTestpUpdateMembersRoleChannel(t *testing.T, rctx request.CTX, ss store
}
assert.ElementsMatch(t, tt.expectedUpdatedUsers, updatedUserIDs)
members, err := ss.Channel().GetMembers(channel.Id, 0, 100)
members, err := ss.Channel().GetMembers(model.ChannelMembersGetOptions{ChannelID: channel.Id, Offset: 0, Limit: 100})
require.NoError(t, err)
assert.GreaterOrEqual(t, len(members), 4) // sanity check for channel membership

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

@@ -1580,9 +1580,9 @@ func (_m *ChannelStore) GetMemberLastViewedAt(ctx context.Context, channelID str
return r0, r1
}
// GetMembers provides a mock function with given fields: channelID, offset, limit
func (_m *ChannelStore) GetMembers(channelID string, offset int, limit int) (model.ChannelMembers, error) {
ret := _m.Called(channelID, offset, limit)
// GetMembers provides a mock function with given fields: opts
func (_m *ChannelStore) GetMembers(opts model.ChannelMembersGetOptions) (model.ChannelMembers, error) {
ret := _m.Called(opts)
if len(ret) == 0 {
panic("no return value specified for GetMembers")
@@ -1590,19 +1590,19 @@ func (_m *ChannelStore) GetMembers(channelID string, offset int, limit int) (mod
var r0 model.ChannelMembers
var r1 error
if rf, ok := ret.Get(0).(func(string, int, int) (model.ChannelMembers, error)); ok {
return rf(channelID, offset, limit)
if rf, ok := ret.Get(0).(func(model.ChannelMembersGetOptions) (model.ChannelMembers, error)); ok {
return rf(opts)
}
if rf, ok := ret.Get(0).(func(string, int, int) model.ChannelMembers); ok {
r0 = rf(channelID, offset, limit)
if rf, ok := ret.Get(0).(func(model.ChannelMembersGetOptions) model.ChannelMembers); ok {
r0 = rf(opts)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelMembers)
}
}
if rf, ok := ret.Get(1).(func(string, int, int) error); ok {
r1 = rf(channelID, offset, limit)
if rf, ok := ret.Get(1).(func(model.ChannelMembersGetOptions) error); ok {
r1 = rf(opts)
} else {
r1 = ret.Error(1)
}

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

@@ -368,6 +368,36 @@ func (_m *SharedChannelStore) GetSingleUser(userID string, channelID string, rem
return r0, r1
}
// GetUserChanges provides a mock function with given fields: userID, channelID, afterTime
func (_m *SharedChannelStore) GetUserChanges(userID string, channelID string, afterTime int64) ([]*model.SharedChannelUser, error) {
ret := _m.Called(userID, channelID, afterTime)
if len(ret) == 0 {
panic("no return value specified for GetUserChanges")
}
var r0 []*model.SharedChannelUser
var r1 error
if rf, ok := ret.Get(0).(func(string, string, int64) ([]*model.SharedChannelUser, error)); ok {
return rf(userID, channelID, afterTime)
}
if rf, ok := ret.Get(0).(func(string, string, int64) []*model.SharedChannelUser); ok {
r0 = rf(userID, channelID, afterTime)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.SharedChannelUser)
}
}
if rf, ok := ret.Get(1).(func(string, string, int64) error); ok {
r1 = rf(userID, channelID, afterTime)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetUsersForSync provides a mock function with given fields: filter
func (_m *SharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error) {
ret := _m.Called(filter)
@@ -700,6 +730,42 @@ func (_m *SharedChannelStore) UpdateRemoteCursor(id string, cursor model.GetPost
return r0
}
// UpdateRemoteMembershipCursor provides a mock function with given fields: id, syncTime
func (_m *SharedChannelStore) UpdateRemoteMembershipCursor(id string, syncTime int64) error {
ret := _m.Called(id, syncTime)
if len(ret) == 0 {
panic("no return value specified for UpdateRemoteMembershipCursor")
}
var r0 error
if rf, ok := ret.Get(0).(func(string, int64) error); ok {
r0 = rf(id, syncTime)
} else {
r0 = ret.Error(0)
}
return r0
}
// UpdateUserLastMembershipSyncAt provides a mock function with given fields: userID, channelID, remoteID, syncTime
func (_m *SharedChannelStore) UpdateUserLastMembershipSyncAt(userID string, channelID string, remoteID string, syncTime int64) error {
ret := _m.Called(userID, channelID, remoteID, syncTime)
if len(ret) == 0 {
panic("no return value specified for UpdateUserLastMembershipSyncAt")
}
var r0 error
if rf, ok := ret.Get(0).(func(string, string, string, int64) error); ok {
r0 = rf(userID, channelID, remoteID, syncTime)
} else {
r0 = ret.Error(0)
}
return r0
}
// UpdateUserLastSyncAt provides a mock function with given fields: userID, channelID, remoteID
func (_m *SharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error {
ret := _m.Called(userID, channelID, remoteID)

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

@@ -1729,10 +1729,10 @@ func (s *TimerLayerChannelStore) GetMemberLastViewedAt(ctx context.Context, chan
return result, err
}
func (s *TimerLayerChannelStore) GetMembers(channelID string, offset int, limit int) (model.ChannelMembers, error) {
func (s *TimerLayerChannelStore) GetMembers(opts model.ChannelMembersGetOptions) (model.ChannelMembers, error) {
start := time.Now()
result, err := s.ChannelStore.GetMembers(channelID, offset, limit)
result, err := s.ChannelStore.GetMembers(opts)
elapsed := float64(time.Since(start)) / float64(time.Second)
if s.Root.Metrics != nil {
@@ -9173,6 +9173,22 @@ func (s *TimerLayerSharedChannelStore) GetSingleUser(userID string, channelID st
return result, err
}
func (s *TimerLayerSharedChannelStore) GetUserChanges(userID string, channelID string, afterTime int64) ([]*model.SharedChannelUser, error) {
start := time.Now()
result, err := s.SharedChannelStore.GetUserChanges(userID, channelID, afterTime)
elapsed := float64(time.Since(start)) / float64(time.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("SharedChannelStore.GetUserChanges", success, elapsed)
}
return result, err
}
func (s *TimerLayerSharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error) {
start := time.Now()
@@ -9365,6 +9381,38 @@ func (s *TimerLayerSharedChannelStore) UpdateRemoteCursor(id string, cursor mode
return err
}
func (s *TimerLayerSharedChannelStore) UpdateRemoteMembershipCursor(id string, syncTime int64) error {
start := time.Now()
err := s.SharedChannelStore.UpdateRemoteMembershipCursor(id, syncTime)
elapsed := float64(time.Since(start)) / float64(time.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("SharedChannelStore.UpdateRemoteMembershipCursor", success, elapsed)
}
return err
}
func (s *TimerLayerSharedChannelStore) UpdateUserLastMembershipSyncAt(userID string, channelID string, remoteID string, syncTime int64) error {
start := time.Now()
err := s.SharedChannelStore.UpdateUserLastMembershipSyncAt(userID, channelID, remoteID, syncTime)
elapsed := float64(time.Since(start)) / float64(time.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("SharedChannelStore.UpdateUserLastMembershipSyncAt", success, elapsed)
}
return err
}
func (s *TimerLayerSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error {
start := time.Now()