* - columns added to ShareChannelRemotes: lastpostcreateat, lastpostupdateat
- SyncMsg and SyncResponse moved to `model` package
- field added to RemoteCluster struct: PluginID

* sync new posts before updated posts to ensure post order in MS Teams

* add plugid to remoteclusters table and store

* don't sync history by default
Этот коммит содержится в:
Doug Lauder
2023-12-04 13:10:20 -05:00
коммит произвёл GitHub
родитель b2ec1ff8ae
Коммит 8bf9e4c481
22 изменённых файлов: 471 добавлений и 132 удалений

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

@@ -230,6 +230,8 @@ channels/db/migrations/mysql/000115_user_reporting_changes.down.sql
channels/db/migrations/mysql/000115_user_reporting_changes.up.sql
channels/db/migrations/mysql/000116_create_outgoing_oauth_connections.down.sql
channels/db/migrations/mysql/000116_create_outgoing_oauth_connections.up.sql
channels/db/migrations/mysql/000117_msteams_shared_channels.down.sql
channels/db/migrations/mysql/000117_msteams_shared_channels.up.sql
channels/db/migrations/postgres/000001_create_teams.down.sql
channels/db/migrations/postgres/000001_create_teams.up.sql
channels/db/migrations/postgres/000002_create_team_members.down.sql
@@ -460,3 +462,5 @@ channels/db/migrations/postgres/000115_user_reporting_changes.down.sql
channels/db/migrations/postgres/000115_user_reporting_changes.up.sql
channels/db/migrations/postgres/000116_create_outgoing_oauth_connections.down.sql
channels/db/migrations/postgres/000116_create_outgoing_oauth_connections.up.sql
channels/db/migrations/postgres/000117_msteams_shared_channels.down.sql
channels/db/migrations/postgres/000117_msteams_shared_channels.up.sql

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

@@ -0,0 +1,47 @@
SET @preparedStatement = (SELECT IF(
EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'RemoteClusters'
AND table_schema = DATABASE()
AND column_name = 'PluginID'
),
'ALTER TABLE RemoteClusters DROP COLUMN PluginID;',
'SELECT 1;'
));
PREPARE removeColumnIfExists FROM @preparedStatement;
EXECUTE removeColumnIfExists;
DEALLOCATE PREPARE removeColumnIfExists;
SET @preparedStatement = (SELECT IF(
EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'SharedChannelRemotes'
AND table_schema = DATABASE()
AND column_name = 'LastPostCreateAt'
),
'ALTER TABLE SharedChannelRemotes DROP COLUMN LastPostCreateAt;',
'SELECT 1;'
));
PREPARE removeColumnIfExists FROM @preparedStatement;
EXECUTE removeColumnIfExists;
DEALLOCATE PREPARE removeColumnIfExists;
SET @preparedStatement = (SELECT IF(
EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'SharedChannelRemotes'
AND table_schema = DATABASE()
AND column_name = 'LastPostCreateID'
),
'ALTER TABLE SharedChannelRemotes DROP COLUMN LastPostCreateID;',
'SELECT 1;'
));
PREPARE removeColumnIfExists FROM @preparedStatement;
EXECUTE removeColumnIfExists;
DEALLOCATE PREPARE removeColumnIfExists;

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

@@ -0,0 +1,47 @@
SET @preparedStatement = (SELECT IF(
NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'RemoteClusters'
AND table_schema = DATABASE()
AND column_name = 'PluginID'
),
'ALTER TABLE RemoteClusters ADD COLUMN PluginID varchar(190) NOT NULL DEFAULT \'\';',
'SELECT 1;'
));
PREPARE addColumnIfNotExists FROM @preparedStatement;
EXECUTE addColumnIfNotExists;
DEALLOCATE PREPARE addColumnIfNotExists;
SET @preparedStatement = (SELECT IF(
NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'SharedChannelRemotes'
AND table_schema = DATABASE()
AND column_name = 'LastPostCreateAt'
),
'ALTER TABLE SharedChannelRemotes ADD COLUMN LastPostCreateAt bigint NOT NULL DEFAULT 0;',
'SELECT 1;'
));
PREPARE addColumnIfNotExists FROM @preparedStatement;
EXECUTE addColumnIfNotExists;
DEALLOCATE PREPARE addColumnIfNotExists;
SET @preparedStatement = (SELECT IF(
NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'SharedChannelRemotes'
AND table_schema = DATABASE()
AND column_name = 'LastPostCreateID'
),
'ALTER TABLE SharedChannelRemotes ADD COLUMN LastPostCreateID varchar(26);',
'SELECT 1;'
));
PREPARE addColumnIfNotExists FROM @preparedStatement;
EXECUTE addColumnIfNotExists;
DEALLOCATE PREPARE addColumnIfNotExists;

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

@@ -0,0 +1,6 @@
ALTER TABLE RemoteClusters DROP COLUMN IF EXISTS PluginID;
ALTER TABLE SharedChannelRemotes DROP COLUMN IF EXISTS LastPostCreateAt;
ALTER TABLE SharedChannelRemotes DROP COLUMN IF EXISTS LastPostCreateID;

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

@@ -0,0 +1,6 @@
ALTER TABLE RemoteClusters ADD COLUMN IF NOT EXISTS PluginID VARCHAR(190) NOT NULL DEFAULT '';
ALTER TABLE SharedChannelRemotes ADD COLUMN IF NOT EXISTS LastPostCreateAt bigint NOT NULL DEFAULT 0;
ALTER TABLE SharedChannelRemotes ADD COLUMN IF NOT EXISTS LastPostCreateID VARCHAR(26);

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

@@ -13,9 +13,10 @@ import (
"sync"
"time"
sq "github.com/mattermost/squirrel"
"github.com/pkg/errors"
sq "github.com/mattermost/squirrel"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/request"
@@ -1396,10 +1397,22 @@ func (s *SqlPostStore) GetPostsSinceForSync(options model.GetPostsSinceForSyncOp
query := s.getQueryBuilder().
Select("*").
From("Posts").
Where(sq.Or{sq.Gt{"Posts.UpdateAt": cursor.LastPostUpdateAt}, sq.And{sq.Eq{"Posts.UpdateAt": cursor.LastPostUpdateAt}, sq.Gt{"Posts.Id": cursor.LastPostId}}}).
OrderBy("Posts.UpdateAt", "Id").
Limit(uint64(limit))
if options.SinceCreateAt {
query = query.Where(sq.Or{
sq.Gt{"Posts.CreateAt": cursor.LastPostCreateAt},
sq.And{
sq.Eq{"Posts.CreateAt": cursor.LastPostCreateAt},
sq.Gt{"Posts.Id": cursor.LastPostCreateID},
},
})
} else {
query = query.Where(sq.Or{sq.Gt{"Posts.UpdateAt": cursor.LastPostUpdateAt},
sq.And{sq.Eq{"Posts.UpdateAt": cursor.LastPostUpdateAt}, sq.Gt{"Posts.Id": cursor.LastPostUpdateID}}})
}
if options.ChannelId != "" {
query = query.Where(sq.Eq{"Posts.ChannelId": options.ChannelId})
}
@@ -1424,8 +1437,13 @@ func (s *SqlPostStore) GetPostsSinceForSync(options model.GetPostsSinceForSyncOp
}
if len(posts) != 0 {
cursor.LastPostUpdateAt = posts[len(posts)-1].UpdateAt
cursor.LastPostId = posts[len(posts)-1].Id
if options.SinceCreateAt {
cursor.LastPostCreateAt = posts[len(posts)-1].CreateAt
cursor.LastPostCreateID = posts[len(posts)-1].Id
} else {
cursor.LastPostUpdateAt = posts[len(posts)-1].UpdateAt
cursor.LastPostUpdateID = posts[len(posts)-1].Id
}
}
return posts, cursor, nil
}

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

@@ -7,9 +7,10 @@ import (
"fmt"
"strings"
sq "github.com/mattermost/squirrel"
"github.com/pkg/errors"
sq "github.com/mattermost/squirrel"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/channels/store"
)
@@ -38,6 +39,7 @@ func remoteClusterFields(prefix string) []string {
prefix + "RemoteToken",
prefix + "Topics",
prefix + "CreatorId",
prefix + "PluginID",
}
}
@@ -49,10 +51,10 @@ func (s sqlRemoteClusterStore) Save(remoteCluster *model.RemoteCluster) (*model.
query := `INSERT INTO RemoteClusters
(RemoteId, RemoteTeamId, Name, DisplayName, SiteURL, CreateAt,
LastPingAt, Token, RemoteToken, Topics, CreatorId)
LastPingAt, Token, RemoteToken, Topics, CreatorId, PluginID)
VALUES
(:RemoteId, :RemoteTeamId, :Name, :DisplayName, :SiteURL, :CreateAt,
:LastPingAt, :Token, :RemoteToken, :Topics, :CreatorId)`
:LastPingAt, :Token, :RemoteToken, :Topics, :CreatorId, :PluginID)`
if _, err := s.GetMasterX().NamedExec(query, remoteCluster); err != nil {
return nil, errors.Wrap(err, "failed to save RemoteCluster")
@@ -75,7 +77,8 @@ func (s sqlRemoteClusterStore) Update(remoteCluster *model.RemoteCluster) (*mode
CreatorId = :CreatorId,
DisplayName = :DisplayName,
SiteURL = :SiteURL,
Topics = :Topics
Topics = :Topics,
PluginID = :PluginID
WHERE RemoteId = :RemoteId AND Name = :Name`
if _, err := s.GetMasterX().NamedExec(query, remoteCluster); err != nil {
@@ -149,6 +152,10 @@ func (s sqlRemoteClusterStore) GetAll(filter model.RemoteClusterQueryFilter) ([]
query = query.Where(sq.NotEq{"rc.SiteURL": ""})
}
if filter.PluginID != "" {
query = query.Where(sq.Eq{"rc.PluginID": filter.PluginID})
}
if filter.Topic != "" {
trimmed := strings.TrimSpace(filter.Topic)
if trimmed == "" || trimmed == "*" {

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

@@ -11,8 +11,9 @@ import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/channels/store"
sq "github.com/mattermost/squirrel"
"github.com/pkg/errors"
sq "github.com/mattermost/squirrel"
)
const (
@@ -333,8 +334,10 @@ func (s SqlSharedChannelStore) SaveRemote(remote *model.SharedChannelRemote) (*m
}
query, args, err := s.getQueryBuilder().Insert("SharedChannelRemotes").
Columns("Id", "ChannelId", "CreatorId", "CreateAt", "UpdateAt", "IsInviteAccepted", "IsInviteConfirmed", "RemoteId", "LastPostUpdateAt", "LastPostId").
Values(remote.Id, remote.ChannelId, remote.CreatorId, remote.CreateAt, remote.UpdateAt, remote.IsInviteAccepted, remote.IsInviteConfirmed, remote.RemoteId, remote.LastPostUpdateAt, remote.LastPostId).
Columns("Id", "ChannelId", "CreatorId", "CreateAt", "UpdateAt", "IsInviteAccepted", "IsInviteConfirmed", "RemoteId",
"LastPostCreateAt", "LastPostCreateId", "LastPostUpdateAt", "LastPostId").
Values(remote.Id, remote.ChannelId, remote.CreatorId, remote.CreateAt, remote.UpdateAt, remote.IsInviteAccepted, remote.IsInviteConfirmed, remote.RemoteId,
remote.LastPostCreateAt, remote.LastPostCreateID, remote.LastPostUpdateAt, remote.LastPostUpdateID).
ToSql()
if err != nil {
return nil, errors.Wrapf(err, "savesharedchannelremote_tosql")
@@ -359,8 +362,10 @@ func (s SqlSharedChannelStore) UpdateRemote(remote *model.SharedChannelRemote) (
Set("IsInviteAccepted", remote.IsInviteAccepted).
Set("IsInviteConfirmed", remote.IsInviteConfirmed).
Set("RemoteId", remote.RemoteId).
Set("LastPostCreateAt", remote.LastPostUpdateAt).
Set("LastPostCreateId", remote.LastPostCreateID).
Set("LastPostUpdateAt", remote.LastPostUpdateAt).
Set("LastPostId", remote.LastPostId).
Set("LastPostId", remote.LastPostUpdateID).
Where(sq.And{
sq.Eq{"Id": remote.Id},
sq.Eq{"ChannelId": remote.ChannelId},
@@ -398,8 +403,10 @@ func sharedChannelRemoteFields(prefix string) []string {
prefix + "IsInviteAccepted",
prefix + "IsInviteConfirmed",
prefix + "RemoteId",
prefix + "LastPostCreateAt",
"COALESCE(" + prefix + "LastPostCreateID,'') AS LastPostCreateID",
prefix + "LastPostUpdateAt",
prefix + "LastPostId",
"COALESCE(" + prefix + "LastPostId,'') AS LastPostUpdateID",
}
}
@@ -532,14 +539,32 @@ func (s SqlSharedChannelStore) GetRemoteForUser(remoteId string, userId string)
return &rc, nil
}
// UpdateRemoteCursor updates the LastPostUpdateAt timestamp and LastPostId for the specified SharedChannelRemote.
// UpdateRemoteCursor updates the cursor for the specified SharedChannelRemote.
func (s SqlSharedChannelStore) UpdateRemoteCursor(id string, cursor model.GetPostsSinceForSyncCursor) error {
squery, args, err := s.getQueryBuilder().
var updateNeeded bool
builder := s.getQueryBuilder().
Update("SharedChannelRemotes").
Set("LastPostUpdateAt", cursor.LastPostUpdateAt).
Set("LastPostId", cursor.LastPostId).
Where(sq.Eq{"Id": id}).
ToSql()
Where(sq.Eq{"Id": id})
if cursor.LastPostCreateAt > 0 || cursor.LastPostCreateID != "" {
builder = builder.Set("LastPostCreateAt", cursor.LastPostCreateAt)
builder = builder.Set("LastPostCreateId", cursor.LastPostCreateID)
updateNeeded = true
}
if cursor.LastPostUpdateAt > 0 || cursor.LastPostUpdateID != "" {
builder = builder.Set("LastPostUpdateAt", cursor.LastPostUpdateAt)
builder = builder.Set("LastPostId", cursor.LastPostUpdateID)
updateNeeded = true
}
if !updateNeeded {
// no new cursor provided.
return fmt.Errorf("cursor empty")
}
squery, args, err := builder.ToSql()
if err != nil {
return errors.Wrap(err, "update_shared_channel_remote_cursor_tosql")
}

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

@@ -58,7 +58,8 @@ func TestPostStore(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
t.Run("GetDirectPostParentsForExportAfterBatched", func(t *testing.T) { testPostStoreGetDirectPostParentsForExportAfterBatched(t, rctx, ss, s) })
t.Run("GetForThread", func(t *testing.T) { testPostStoreGetForThread(t, rctx, ss) })
t.Run("HasAutoResponsePostByUserSince", func(t *testing.T) { testHasAutoResponsePostByUserSince(t, rctx, ss) })
t.Run("GetPostsSinceForSync", func(t *testing.T) { testGetPostsSinceForSync(t, rctx, ss, s) })
t.Run("GetPostsSinceUpdateForSync", func(t *testing.T) { testGetPostsSinceUpdateForSync(t, rctx, ss, s) })
t.Run("GetPostsSinceCreateForSync", func(t *testing.T) { testGetPostsSinceCreateForSync(t, rctx, ss, s) })
t.Run("SetPostReminder", func(t *testing.T) { testSetPostReminder(t, rctx, ss, s) })
t.Run("GetPostReminders", func(t *testing.T) { testGetPostReminders(t, rctx, ss, s) })
t.Run("GetPostReminderMetadata", func(t *testing.T) { testGetPostReminderMetadata(t, rctx, ss, s) })
@@ -4655,7 +4656,7 @@ func testHasAutoResponsePostByUserSince(t *testing.T, rctx request.CTX, ss store
})
}
func testGetPostsSinceForSync(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
func testGetPostsSinceUpdateForSync(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
// create some posts.
channelID := model.NewId()
remoteID := model.NewString(model.NewId())
@@ -4758,6 +4759,113 @@ func testGetPostsSinceForSync(t *testing.T, rctx request.CTX, ss store.Store, s
})
}
func testGetPostsSinceCreateForSync(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
// create some posts.
channelID := model.NewId()
remoteID := model.NewString(model.NewId())
first := model.GetMillis()
data := []*model.Post{
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 0"},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 1"},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 2"},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 3", RemoteId: remoteID},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 4", RemoteId: remoteID},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 5", RemoteId: remoteID},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 6", RemoteId: remoteID},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 7"},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 8", DeleteAt: model.GetMillis()},
{Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 9", DeleteAt: model.GetMillis()},
}
for i, p := range data {
p.CreateAt = first + (int64(i) * 300000)
if p.RemoteId == nil {
p.RemoteId = model.NewString(model.NewId())
}
_, err := ss.Post().Save(p)
require.NoError(t, err, "couldn't save post")
}
t.Run("Invalid channel id", func(t *testing.T) {
opt := model.GetPostsSinceForSyncOptions{
ChannelId: model.NewId(),
SinceCreateAt: true,
}
cursor := model.GetPostsSinceForSyncCursor{}
posts, cursorOut, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100)
require.NoError(t, err)
require.Empty(t, posts, "should return zero posts")
require.Equal(t, cursor, cursorOut)
})
t.Run("Get by channel, exclude remotes, exclude deleted", func(t *testing.T) {
opt := model.GetPostsSinceForSyncOptions{
ChannelId: channelID,
ExcludeRemoteId: *remoteID,
SinceCreateAt: true,
}
cursor := model.GetPostsSinceForSyncCursor{}
posts, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100)
require.NoError(t, err)
require.ElementsMatch(t, getPostIds(data[0:3], data[7]), getPostIds(posts))
})
t.Run("Include deleted", func(t *testing.T) {
opt := model.GetPostsSinceForSyncOptions{
ChannelId: channelID,
IncludeDeleted: true,
SinceCreateAt: true,
}
cursor := model.GetPostsSinceForSyncCursor{}
posts, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100)
require.NoError(t, err)
require.ElementsMatch(t, getPostIds(data), getPostIds(posts))
})
t.Run("Limit and cursor", func(t *testing.T) {
opt := model.GetPostsSinceForSyncOptions{
ChannelId: channelID,
SinceCreateAt: true,
}
cursor := model.GetPostsSinceForSyncCursor{}
posts1, cursor, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5)
require.NoError(t, err)
require.Len(t, posts1, 5, "should get 5 posts")
posts2, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5)
require.NoError(t, err)
require.Len(t, posts2, 3, "should get 3 posts")
require.ElementsMatch(t, getPostIds(data[0:8]), getPostIds(posts1, posts2...))
})
t.Run("CreateAt collisions", func(t *testing.T) {
// this test requires all the CreateAt timestamps to be the same.
result, err := s.GetMasterX().Exec("UPDATE Posts SET CreateAt = ?", model.GetMillis())
require.NoError(t, err)
rows, err := result.RowsAffected()
require.NoError(t, err)
require.Greater(t, rows, int64(0))
opt := model.GetPostsSinceForSyncOptions{
ChannelId: channelID,
}
cursor := model.GetPostsSinceForSyncCursor{}
posts1, cursor, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5)
require.NoError(t, err)
require.Len(t, posts1, 5, "should get 5 posts")
posts2, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5)
require.NoError(t, err)
require.Len(t, posts2, 3, "should get 3 posts")
require.ElementsMatch(t, getPostIds(data[0:8]), getPostIds(posts1, posts2...))
})
}
func testSetPostReminder(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
// Basic
userID := NewTestId()

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

@@ -15,6 +15,10 @@ import (
"github.com/stretchr/testify/require"
)
const (
testPluginID = "com.sample.blap"
)
func TestRemoteClusterStore(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("RemoteClusterGetAllInChannel", func(t *testing.T) { testRemoteClusterGetAllInChannel(t, rctx, ss) })
t.Run("RemoteClusterGetAllNotInChannel", func(t *testing.T) { testRemoteClusterGetAllNotInChannel(t, rctx, ss) })
@@ -89,6 +93,7 @@ func testRemoteClusterGet(t *testing.T, rctx request.CTX, ss store.Store) {
Name: "shortlived_remote_2",
SiteURL: "nowhere.com",
CreatorId: model.NewId(),
PluginID: testPluginID,
}
rcSaved, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err)
@@ -96,6 +101,7 @@ func testRemoteClusterGet(t *testing.T, rctx request.CTX, ss store.Store) {
rcGet, err := ss.RemoteCluster().Get(rcSaved.RemoteId)
require.NoError(t, err)
require.Equal(t, rcSaved.RemoteId, rcGet.RemoteId)
require.Equal(t, testPluginID, rcGet.PluginID)
})
t.Run("Get not found", func(t *testing.T) {
@@ -237,8 +243,8 @@ func testRemoteClusterGetAllInChannel(t *testing.T, rctx request.CTX, ss store.S
// Create some remote clusters
rcData := []*model.RemoteCluster{
{Name: "AAAA_Inc", CreatorId: userId, SiteURL: "aaaa.com", RemoteId: model.NewId(), LastPingAt: now},
{Name: "BBBB_Inc", CreatorId: userId, SiteURL: "bbbb.com", RemoteId: model.NewId(), LastPingAt: 0},
{Name: "AAAA_Inc", CreatorId: userId, SiteURL: "aaaa.com", RemoteId: model.NewId(), LastPingAt: now, PluginID: testPluginID},
{Name: "BBBB_Inc", CreatorId: userId, SiteURL: "bbbb.com", RemoteId: model.NewId(), LastPingAt: 0, PluginID: testPluginID},
{Name: "CCCC_Inc", CreatorId: userId, SiteURL: "cccc.com", RemoteId: model.NewId(), LastPingAt: now},
{Name: "DDDD_Inc", CreatorId: userId, SiteURL: "dddd.com", RemoteId: model.NewId(), LastPingAt: now},
{Name: "EEEE_Inc", CreatorId: userId, SiteURL: "eeee.com", RemoteId: model.NewId(), LastPingAt: 0},
@@ -270,6 +276,8 @@ func testRemoteClusterGetAllInChannel(t *testing.T, rctx request.CTX, ss store.S
require.Len(t, list, 2, "channel 1 should have 2 remote clusters")
ids := getIds(list)
require.ElementsMatch(t, []string{rcData[0].RemoteId, rcData[1].RemoteId}, ids)
require.Equal(t, testPluginID, rcData[0].PluginID)
require.Equal(t, testPluginID, rcData[1].PluginID)
})
t.Run("Channel 1 online only", func(t *testing.T) {

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

@@ -765,28 +765,52 @@ func testUpdateSharedChannelRemoteCursor(t *testing.T, rctx request.CTX, ss stor
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save remote", err)
future := model.GetMillis() + 3600000 // 1 hour in the future
postID := model.NewId()
futureCreateAt := model.GetMillis() + 3600000 // 1 hour in the future
postCreateID := model.NewId()
cursor := model.GetPostsSinceForSyncCursor{
LastPostUpdateAt: future,
LastPostId: postID,
futureUpdateAt := model.GetMillis() + (3600000 * 2) // 2 hours in the future
postUpdateID := model.NewId()
cursorCreate := model.GetPostsSinceForSyncCursor{
LastPostCreateAt: futureCreateAt,
LastPostCreateID: postCreateID,
}
t.Run("Update NextSyncAt for remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, cursor)
require.NoError(t, err, "update NextSyncAt should not error", err)
cursorUpdate := model.GetPostsSinceForSyncCursor{
LastPostUpdateAt: futureUpdateAt,
LastPostUpdateID: postUpdateID,
}
t.Run("Update cursor CreateAt for remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, cursorCreate)
require.NoError(t, err, "update cursor should not error", err)
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err)
require.Equal(t, future, r.LastPostUpdateAt)
require.Equal(t, postID, r.LastPostId)
require.Equal(t, futureCreateAt, r.LastPostCreateAt)
require.Equal(t, postCreateID, r.LastPostCreateID)
})
t.Run("Update NextSyncAt for non-existent shared channel remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(model.NewId(), cursor)
t.Run("Update cursor UpdateAt for remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, cursorUpdate)
require.NoError(t, err, "update cursor should not error", err)
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err)
require.Equal(t, futureUpdateAt, r.LastPostUpdateAt)
require.Equal(t, postUpdateID, r.LastPostUpdateID)
})
t.Run("Update cursor for non-existent shared channel remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(model.NewId(), cursorUpdate)
require.Error(t, err, "update non-existent remote should error", err)
})
t.Run("Update with empty cursor", func(t *testing.T) {
emptyCursor := model.GetPostsSinceForSyncCursor{}
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, emptyCursor)
require.Error(t, err, "update with empty cursor should error", err)
})
}
func testDeleteSharedChannelRemote(t *testing.T, rctx request.CTX, ss store.Store) {