Migrate ChannelMemberHistory store to Sync by default (#11331)

Этот коммит содержится в:
Jesús Espino
2019-06-26 09:39:43 +02:00
коммит произвёл GitHub
родитель d17bdc6764
Коммит 8f0216c57f
8 изменённых файлов: 217 добавлений и 166 удалений

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

@@ -96,8 +96,8 @@ func (a *App) JoinDefaultChannels(teamId string, user *model.User, shouldBeAdmin
if cmResult := <-a.Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil { if cmResult := <-a.Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil {
err = cmResult.Err err = cmResult.Err
} }
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { if histErr := a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); histErr != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", histErr))
} }
if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
@@ -243,8 +243,8 @@ func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Chan
if cmresult := <-a.Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil { if cmresult := <-a.Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
return nil, cmresult.Err return nil, cmresult.Err
} }
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(channel.CreatorId, sc.Id, model.GetMillis()); result.Err != nil { if err := a.Srv.Store.ChannelMemberHistory().LogJoinEvent(channel.CreatorId, sc.Id, model.GetMillis()); err != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", err))
} }
a.InvalidateCacheForUser(channel.CreatorId) a.InvalidateCacheForUser(channel.CreatorId)
@@ -358,11 +358,11 @@ func (a *App) createDirectChannel(userId string, otherUserId string) (*model.Cha
return nil, err return nil, err
} }
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId, channel.Id, model.GetMillis()); result.Err != nil { if err = a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId, channel.Id, model.GetMillis()); err != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", err))
} }
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(otherUserId, channel.Id, model.GetMillis()); result.Err != nil { if err = a.Srv.Store.ChannelMemberHistory().LogJoinEvent(otherUserId, channel.Id, model.GetMillis()); err != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", err))
} }
return channel, nil return channel, nil
@@ -470,8 +470,8 @@ func (a *App) createGroupChannel(userIds []string, creatorId string) (*model.Cha
if result := <-a.Srv.Store.Channel().SaveMember(cm); result.Err != nil { if result := <-a.Srv.Store.Channel().SaveMember(cm); result.Err != nil {
return nil, result.Err return nil, result.Err
} }
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { if err := a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", err))
} }
} }
@@ -927,8 +927,8 @@ func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMem
} }
a.WaitForChannelMembership(channel.Id, user.Id) a.WaitForChannelMembership(channel.Id, user.Id)
if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { if err = a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil {
mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", err))
} }
a.InvalidateCacheForUser(user.Id) a.InvalidateCacheForUser(user.Id)
@@ -1606,8 +1606,8 @@ func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string,
if err := a.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); err != nil { if err := a.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); err != nil {
return err return err
} }
if cmhResult := <-a.Srv.Store.ChannelMemberHistory().LogLeaveEvent(userIdToRemove, channel.Id, model.GetMillis()); cmhResult.Err != nil { if err := a.Srv.Store.ChannelMemberHistory().LogLeaveEvent(userIdToRemove, channel.Id, model.GetMillis()); err != nil {
return cmhResult.Err return err
} }
a.InvalidateCacheForUser(userIdToRemove) a.InvalidateCacheForUser(userIdToRemove)

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

@@ -13,7 +13,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
) )
func TestPermanentDeleteChannel(t *testing.T) { func TestPermanentDeleteChannel(t *testing.T) {
@@ -165,14 +164,17 @@ func TestJoinDefaultChannelsCreatesChannelMemberHistoryRecordTownSquare(t *testi
channel, err := th.App.Srv.Store.Channel().GetByName(th.BasicTeam.Id, "town-square", true) channel, err := th.App.Srv.Store.Channel().GetByName(th.BasicTeam.Id, "town-square", true)
require.Nil(t, err) require.Nil(t, err)
townSquareChannelId := channel.Id townSquareChannelId := channel.Id
initialNumTownSquareUsers := len(store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, townSquareChannelId)).([]*model.ChannelMemberHistoryResult)) users, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, townSquareChannelId)
require.Nil(t, err)
initialNumTownSquareUsers := len(users)
// create a new user that joins the default channels // create a new user that joins the default channels
user := th.CreateUser() user := th.CreateUser()
th.App.JoinDefaultChannels(th.BasicTeam.Id, user, false, "") th.App.JoinDefaultChannels(th.BasicTeam.Id, user, false, "")
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, townSquareChannelId)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, townSquareChannelId)
require.Nil(t, err)
assert.Len(t, histories, initialNumTownSquareUsers+1) assert.Len(t, histories, initialNumTownSquareUsers+1)
found := false found := false
@@ -193,14 +195,17 @@ func TestJoinDefaultChannelsCreatesChannelMemberHistoryRecordOffTopic(t *testing
channel, err := th.App.Srv.Store.Channel().GetByName(th.BasicTeam.Id, "off-topic", true) channel, err := th.App.Srv.Store.Channel().GetByName(th.BasicTeam.Id, "off-topic", true)
require.Nil(t, err) require.Nil(t, err)
offTopicChannelId := channel.Id offTopicChannelId := channel.Id
initialNumTownSquareUsers := len(store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, offTopicChannelId)).([]*model.ChannelMemberHistoryResult)) users, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, offTopicChannelId)
require.Nil(t, err)
initialNumTownSquareUsers := len(users)
// create a new user that joins the default channels // create a new user that joins the default channels
user := th.CreateUser() user := th.CreateUser()
th.App.JoinDefaultChannels(th.BasicTeam.Id, user, false, "") th.App.JoinDefaultChannels(th.BasicTeam.Id, user, false, "")
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, offTopicChannelId)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, offTopicChannelId)
require.Nil(t, err)
assert.Len(t, histories, initialNumTownSquareUsers+1) assert.Len(t, histories, initialNumTownSquareUsers+1)
found := false found := false
@@ -251,7 +256,8 @@ func TestCreateChannelPublicCreatesChannelMemberHistoryRecord(t *testing.T) {
publicChannel := th.createChannel(th.BasicTeam, model.CHANNEL_OPEN) publicChannel := th.createChannel(th.BasicTeam, model.CHANNEL_OPEN)
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, publicChannel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, publicChannel.Id)
require.Nil(t, err)
assert.Len(t, histories, 1) assert.Len(t, histories, 1)
assert.Equal(t, th.BasicUser.Id, histories[0].UserId) assert.Equal(t, th.BasicUser.Id, histories[0].UserId)
assert.Equal(t, publicChannel.Id, histories[0].ChannelId) assert.Equal(t, publicChannel.Id, histories[0].ChannelId)
@@ -265,7 +271,8 @@ func TestCreateChannelPrivateCreatesChannelMemberHistoryRecord(t *testing.T) {
privateChannel := th.createChannel(th.BasicTeam, model.CHANNEL_PRIVATE) privateChannel := th.createChannel(th.BasicTeam, model.CHANNEL_PRIVATE)
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, privateChannel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, privateChannel.Id)
require.Nil(t, err)
assert.Len(t, histories, 1) assert.Len(t, histories, 1)
assert.Equal(t, th.BasicUser.Id, histories[0].UserId) assert.Equal(t, th.BasicUser.Id, histories[0].UserId)
assert.Equal(t, privateChannel.Id, histories[0].ChannelId) assert.Equal(t, privateChannel.Id, histories[0].ChannelId)
@@ -302,7 +309,8 @@ func TestCreateGroupChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
t.Fatal("Failed to create group channel. Error: " + err.Message) t.Fatal("Failed to create group channel. Error: " + err.Message)
} else { } else {
// there should be a ChannelMemberHistory record for each user // there should be a ChannelMemberHistory record for each user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)
require.Nil(t, err)
assert.Len(t, histories, 3) assert.Len(t, histories, 3)
channelMemberHistoryUserIds := make([]string, 0) channelMemberHistoryUserIds := make([]string, 0)
@@ -328,7 +336,8 @@ func TestCreateDirectChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
t.Fatal("Failed to create direct channel. Error: " + err.Message) t.Fatal("Failed to create direct channel. Error: " + err.Message)
} else { } else {
// there should be a ChannelMemberHistory record for both users // there should be a ChannelMemberHistory record for both users
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)
require.Nil(t, err)
assert.Len(t, histories, 2) assert.Len(t, histories, 2)
historyId0 := histories[0].UserId historyId0 := histories[0].UserId
@@ -356,7 +365,8 @@ func TestGetDirectChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
t.Fatal("Failed to create direct channel. Error: " + err.Message) t.Fatal("Failed to create direct channel. Error: " + err.Message)
} else { } else {
// there should be a ChannelMemberHistory record for both users // there should be a ChannelMemberHistory record for both users
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)
require.Nil(t, err)
assert.Len(t, histories, 2) assert.Len(t, histories, 2)
historyId0 := histories[0].UserId historyId0 := histories[0].UserId
@@ -392,7 +402,8 @@ func TestAddUserToChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
} }
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)
require.Nil(t, err)
assert.Len(t, histories, 2) assert.Len(t, histories, 2)
channelMemberHistoryUserIds := make([]string, 0) channelMemberHistoryUserIds := make([]string, 0)
for _, history := range histories { for _, history := range histories {
@@ -408,7 +419,8 @@ func TestAddUserToChannelCreatesChannelMemberHistoryRecord(t *testing.T) {
// a user creates a channel // a user creates a channel
publicChannel := th.createChannel(th.BasicTeam, model.CHANNEL_OPEN) publicChannel := th.createChannel(th.BasicTeam, model.CHANNEL_OPEN)
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, publicChannel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, publicChannel.Id)
require.Nil(t, err)
assert.Len(t, histories, 1) assert.Len(t, histories, 1)
assert.Equal(t, th.BasicUser.Id, histories[0].UserId) assert.Equal(t, th.BasicUser.Id, histories[0].UserId)
assert.Equal(t, publicChannel.Id, histories[0].ChannelId) assert.Equal(t, publicChannel.Id, histories[0].ChannelId)
@@ -447,7 +459,8 @@ func TestAddChannelMemberNoUserRequestor(t *testing.T) {
} }
// there should be a ChannelMemberHistory record for the user // there should be a ChannelMemberHistory record for the user
histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) histories, err := th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)
require.Nil(t, err)
assert.Len(t, histories, 2) assert.Len(t, histories, 2)
channelMemberHistoryUserIds := make([]string, 0) channelMemberHistoryUserIds := make([]string, 0)
for _, history := range histories { for _, history := range histories {

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

@@ -294,9 +294,9 @@ func TestCreateDefaultMemberships(t *testing.T) {
timeAfterLeaving := model.GetMillis() timeAfterLeaving := model.GetMillis()
// Purging channelmemberhistory doesn't re-add user to channel // Purging channelmemberhistory doesn't re-add user to channel
result := <-th.App.Srv.Store.ChannelMemberHistory().PermanentDeleteBatch(timeBeforeLeaving, 1000) _, err = th.App.Srv.Store.ChannelMemberHistory().PermanentDeleteBatch(timeBeforeLeaving, 1000)
if result.Err != nil { if err != nil {
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error()) t.Errorf("error permanently deleting channelmemberhistory: %s", err.Error())
} }
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt) pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
@@ -310,9 +310,9 @@ func TestCreateDefaultMemberships(t *testing.T) {
} }
// Purging channelmemberhistory doesn't re-add user to channel // Purging channelmemberhistory doesn't re-add user to channel
result = <-th.App.Srv.Jobs.Store.ChannelMemberHistory().PermanentDeleteBatch(timeAfterLeaving, 1000) _, err = th.App.Srv.Jobs.Store.ChannelMemberHistory().PermanentDeleteBatch(timeAfterLeaving, 1000)
if result.Err != nil { if err != nil {
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error()) t.Errorf("error permanently deleting channelmemberhistory: %s", err.Error())
} }
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt) pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)

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

@@ -33,62 +33,64 @@ func NewSqlChannelMemberHistoryStore(sqlStore SqlStore) store.ChannelMemberHisto
return s return s
} }
func (s SqlChannelMemberHistoryStore) LogJoinEvent(userId string, channelId string, joinTime int64) store.StoreChannel { func (s SqlChannelMemberHistoryStore) LogJoinEvent(userId string, channelId string, joinTime int64) *model.AppError {
return store.Do(func(result *store.StoreResult) { channelMemberHistory := &model.ChannelMemberHistory{
channelMemberHistory := &model.ChannelMemberHistory{ UserId: userId,
UserId: userId, ChannelId: channelId,
ChannelId: channelId, JoinTime: joinTime,
JoinTime: joinTime, }
}
if err := s.GetMaster().Insert(channelMemberHistory); err != nil { if err := s.GetMaster().Insert(channelMemberHistory); err != nil {
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.LogJoinEvent", "store.sql_channel_member_history.log_join_event.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("SqlChannelMemberHistoryStore.LogJoinEvent", "store.sql_channel_member_history.log_join_event.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
}) return nil
} }
func (s SqlChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) store.StoreChannel { func (s SqlChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) *model.AppError {
return store.Do(func(result *store.StoreResult) { query := `
query := ` UPDATE ChannelMemberHistory
UPDATE ChannelMemberHistory SET LeaveTime = :LeaveTime
SET LeaveTime = :LeaveTime WHERE UserId = :UserId
WHERE UserId = :UserId AND ChannelId = :ChannelId
AND ChannelId = :ChannelId AND LeaveTime IS NULL`
AND LeaveTime IS NULL`
params := map[string]interface{}{"UserId": userId, "ChannelId": channelId, "LeaveTime": leaveTime} params := map[string]interface{}{"UserId": userId, "ChannelId": channelId, "LeaveTime": leaveTime}
if sqlResult, err := s.GetMaster().Exec(query, params); err != nil { sqlResult, err := s.GetMaster().Exec(query, params)
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.LogLeaveEvent", "store.sql_channel_member_history.log_leave_event.update_error", params, err.Error(), http.StatusInternalServerError) if err != nil {
} else if rows, err := sqlResult.RowsAffected(); err == nil && rows != 1 { return model.NewAppError("SqlChannelMemberHistoryStore.LogLeaveEvent", "store.sql_channel_member_history.log_leave_event.update_error", params, err.Error(), http.StatusInternalServerError)
// there was no join event to update - this is best effort, so no need to raise an error }
mlog.Warn(fmt.Sprintf("Channel join event for user %v and channel %v not found", userId, channelId), mlog.String("user_id", userId))
} if rows, err := sqlResult.RowsAffected(); err == nil && rows != 1 {
}) // there was no join event to update - this is best effort, so no need to raise an error
mlog.Warn(fmt.Sprintf("Channel join event for user %v and channel %v not found", userId, channelId), mlog.String("user_id", userId))
}
return nil
} }
func (s SqlChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) store.StoreChannel { func (s SqlChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, *model.AppError) {
return store.Do(func(result *store.StoreResult) { useChannelMemberHistory, err := s.hasDataAtOrBefore(startTime)
if useChannelMemberHistory, err := s.hasDataAtOrBefore(startTime); err != nil { if err != nil {
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err.Error(), http.StatusInternalServerError)
} else if useChannelMemberHistory { }
// the export period starts after the ChannelMemberHistory table was first introduced, so we can use the
// data from it for our export if useChannelMemberHistory {
if channelMemberHistories, err := s.getFromChannelMemberHistoryTable(startTime, endTime, channelId); err != nil { // the export period starts after the ChannelMemberHistory table was first introduced, so we can use the
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err.Error(), http.StatusInternalServerError) // data from it for our export
} else { channelMemberHistories, err2 := s.getFromChannelMemberHistoryTable(startTime, endTime, channelId)
result.Data = channelMemberHistories if err2 != nil {
} return nil, model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err2.Error(), http.StatusInternalServerError)
} else {
// the export period starts before the ChannelMemberHistory table was introduced, so we need to fake the
// data by assuming that anybody who has ever joined the channel in question was present during the export period.
// this may not always be true, but it's better than saying that somebody wasn't there when they were
if channelMemberHistories, err := s.getFromChannelMembersTable(startTime, endTime, channelId); err != nil {
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err.Error(), http.StatusInternalServerError)
} else {
result.Data = channelMemberHistories
}
} }
}) return channelMemberHistories, nil
}
// the export period starts before the ChannelMemberHistory table was introduced, so we need to fake the
// data by assuming that anybody who has ever joined the channel in question was present during the export period.
// this may not always be true, but it's better than saying that somebody wasn't there when they were
channelMemberHistories, err := s.getFromChannelMembersTable(startTime, endTime, channelId)
if err != nil {
return nil, model.NewAppError("SqlChannelMemberHistoryStore.GetUsersInChannelAt", "store.sql_channel_member_history.get_users_in_channel_during.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return channelMemberHistories, nil
} }
func (s SqlChannelMemberHistoryStore) hasDataAtOrBefore(time int64) (bool, error) { func (s SqlChannelMemberHistoryStore) hasDataAtOrBefore(time int64) (bool, error) {
@@ -159,35 +161,34 @@ func (s SqlChannelMemberHistoryStore) getFromChannelMembersTable(startTime int64
} }
} }
func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) store.StoreChannel { func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, *model.AppError) {
return store.Do(func(result *store.StoreResult) { var query string
var query string if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { query =
query = `DELETE FROM ChannelMemberHistory
`DELETE FROM ChannelMemberHistory
WHERE ctid IN ( WHERE ctid IN (
SELECT ctid FROM ChannelMemberHistory SELECT ctid FROM ChannelMemberHistory
WHERE LeaveTime IS NOT NULL WHERE LeaveTime IS NOT NULL
AND LeaveTime <= :EndTime AND LeaveTime <= :EndTime
LIMIT :Limit LIMIT :Limit
);` );`
} else { } else {
query = query =
`DELETE FROM ChannelMemberHistory `DELETE FROM ChannelMemberHistory
WHERE LeaveTime IS NOT NULL WHERE LeaveTime IS NOT NULL
AND LeaveTime <= :EndTime AND LeaveTime <= :EndTime
LIMIT :Limit` LIMIT :Limit`
} }
params := map[string]interface{}{"EndTime": endTime, "Limit": limit} params := map[string]interface{}{"EndTime": endTime, "Limit": limit}
if sqlResult, err := s.GetMaster().Exec(query, params); err != nil { sqlResult, err := s.GetMaster().Exec(query, params)
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.PermanentDeleteBatchForChannel", "store.sql_channel_member_history.permanent_delete_batch.app_error", params, err.Error(), http.StatusInternalServerError) if err != nil {
} else { return int64(0), model.NewAppError("SqlChannelMemberHistoryStore.PermanentDeleteBatchForChannel", "store.sql_channel_member_history.permanent_delete_batch.app_error", params, err.Error(), http.StatusInternalServerError)
if rowsAffected, err1 := sqlResult.RowsAffected(); err1 != nil { }
result.Err = model.NewAppError("SqlChannelMemberHistoryStore.PermanentDeleteBatchForChannel", "store.sql_channel_member_history.permanent_delete_batch.app_error", params, err.Error(), http.StatusInternalServerError)
} else { rowsAffected, err := sqlResult.RowsAffected()
result.Data = rowsAffected if err != nil {
} return int64(0), model.NewAppError("SqlChannelMemberHistoryStore.PermanentDeleteBatchForChannel", "store.sql_channel_member_history.permanent_delete_batch.app_error", params, err.Error(), http.StatusInternalServerError)
} }
}) return rowsAffected, nil
} }

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

@@ -205,10 +205,10 @@ type ChannelStore interface {
} }
type ChannelMemberHistoryStore interface { type ChannelMemberHistoryStore interface {
LogJoinEvent(userId string, channelId string, joinTime int64) StoreChannel LogJoinEvent(userId string, channelId string, joinTime int64) *model.AppError
LogLeaveEvent(userId string, channelId string, leaveTime int64) StoreChannel LogLeaveEvent(userId string, channelId string, leaveTime int64) *model.AppError
GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) StoreChannel GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, *model.AppError)
PermanentDeleteBatch(endTime int64, limit int64) StoreChannel PermanentDeleteBatch(endTime int64, limit int64) (int64, *model.AppError)
} }
type PostStore interface { type PostStore interface {

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

@@ -42,8 +42,8 @@ func testLogJoinEvent(t *testing.T, ss store.Store) {
user = *store.Must(ss.User().Save(&user)).(*model.User) user = *store.Must(ss.User().Save(&user)).(*model.User)
// log a join event // log a join event
result := <-ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis())
assert.Nil(t, result.Err) assert.Nil(t, err)
} }
func testLogLeaveEvent(t *testing.T, ss store.Store) { func testLogLeaveEvent(t *testing.T, ss store.Store) {
@@ -66,11 +66,11 @@ func testLogLeaveEvent(t *testing.T, ss store.Store) {
user = *store.Must(ss.User().Save(&user)).(*model.User) user = *store.Must(ss.User().Save(&user)).(*model.User)
// log a join event, followed by a leave event // log a join event, followed by a leave event
result := <-ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis())
assert.Nil(t, result.Err) assert.Nil(t, err)
result = <-ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis()) err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis())
assert.Nil(t, result.Err) assert.Nil(t, err)
} }
func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) { func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
@@ -97,20 +97,25 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
// us from looking in the ChannelMembers table for data that isn't found in the ChannelMemberHistory table // us from looking in the ChannelMembers table for data that isn't found in the ChannelMemberHistory table
leaveTime := model.GetMillis() - 20000 leaveTime := model.GetMillis() - 20000
joinTime := leaveTime - 10000 joinTime := leaveTime - 10000
store.Must(ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)
store.Must(ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)) require.Nil(t, err)
err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)
require.Nil(t, err)
// log a join event // log a join event
leaveTime = model.GetMillis() leaveTime = model.GetMillis()
joinTime = leaveTime - 10000 joinTime = leaveTime - 10000
store.Must(ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)
require.Nil(t, err)
// case 1: user joins and leaves the channel before the export period begins // case 1: user joins and leaves the channel before the export period begins
channelMembers := store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 0) assert.Len(t, channelMembers, 0)
// case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends // case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -120,7 +125,8 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
assert.Nil(t, channelMembers[0].LeaveTime) assert.Nil(t, channelMembers[0].LeaveTime)
// case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends // case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -130,10 +136,12 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
assert.Nil(t, channelMembers[0].LeaveTime) assert.Nil(t, channelMembers[0].LeaveTime)
// add a leave time for the user // add a leave time for the user
store.Must(ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)) err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)
require.Nil(t, err)
// case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends // case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -143,7 +151,8 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime) assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime)
// case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends // case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -153,7 +162,8 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime) assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime)
// case 6: user has joined and left the channel long before the export period begins // case 6: user has joined and left the channel long before the export period begins
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 0) assert.Len(t, channelMembers, 0)
} }
@@ -179,11 +189,10 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
// clear any existing ChannelMemberHistory data that might interfere with our test // clear any existing ChannelMemberHistory data that might interfere with our test
var tableDataTruncated = false var tableDataTruncated = false
for !tableDataTruncated { for !tableDataTruncated {
if result := <-ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis(), 1000); result.Err != nil { var count int64
assert.Fail(t, "Failed to truncate ChannelMemberHistory contents", result.Err.Error()) count, err = ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis(), 1000)
} else { require.Nil(t, err, "Failed to truncate ChannelMemberHistory contents")
tableDataTruncated = result.Data.(int64) == int64(0) tableDataTruncated = count == int64(0)
}
} }
// in this test, we're pretending that Message Export was not activated during the export period, so there's no data // in this test, we're pretending that Message Export was not activated during the export period, so there's no data
@@ -200,7 +209,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
// the past, even though the time that they were actually in the channel doesn't necessarily overlap with the export period // the past, even though the time that they were actually in the channel doesn't necessarily overlap with the export period
// case 1: user joins and leaves the channel before the export period begins // case 1: user joins and leaves the channel before the export period begins
channelMembers := store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -210,7 +220,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
assert.Equal(t, joinTime-100, *channelMembers[0].LeaveTime) assert.Equal(t, joinTime-100, *channelMembers[0].LeaveTime)
// case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends // case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -220,7 +231,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime) assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime)
// case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends // case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -230,7 +242,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime) assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime)
// case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends // case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -240,7 +253,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
assert.Equal(t, leaveTime-100, *channelMembers[0].LeaveTime) assert.Equal(t, leaveTime-100, *channelMembers[0].LeaveTime)
// case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends // case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -250,7 +264,8 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
assert.Equal(t, leaveTime+100, *channelMembers[0].LeaveTime) assert.Equal(t, leaveTime+100, *channelMembers[0].LeaveTime)
// case 6: user has joined and left the channel long before the export period begins // case 6: user has joined and left the channel long before the export period begins
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, channel.Id, channelMembers[0].ChannelId) assert.Equal(t, channel.Id, channelMembers[0].ChannelId)
assert.Equal(t, user.Id, channelMembers[0].UserId) assert.Equal(t, user.Id, channelMembers[0].UserId)
@@ -289,22 +304,28 @@ func testPermanentDeleteBatch(t *testing.T, ss store.Store) {
// user1 joins and leaves the channel // user1 joins and leaves the channel
leaveTime := model.GetMillis() leaveTime := model.GetMillis()
joinTime := leaveTime - 10000 joinTime := leaveTime - 10000
store.Must(ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime)
store.Must(ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)) require.Nil(t, err)
err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime)
require.Nil(t, err)
// user2 joins the channel but never leaves // user2 joins the channel but never leaves
store.Must(ss.ChannelMemberHistory().LogJoinEvent(user2.Id, channel.Id, joinTime)) err = ss.ChannelMemberHistory().LogJoinEvent(user2.Id, channel.Id, joinTime)
require.Nil(t, err)
// in between the join time and the leave time, both users were members of the channel // in between the join time and the leave time, both users were members of the channel
channelMembers := store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 2) assert.Len(t, channelMembers, 2)
// the permanent delete should delete at least one record // the permanent delete should delete at least one record
rowsDeleted := store.Must(ss.ChannelMemberHistory().PermanentDeleteBatch(leaveTime, math.MaxInt64)).(int64) rowsDeleted, err := ss.ChannelMemberHistory().PermanentDeleteBatch(leaveTime, math.MaxInt64)
require.Nil(t, err)
assert.NotEqual(t, int64(0), rowsDeleted) assert.NotEqual(t, int64(0), rowsDeleted)
// after the delete, there should be one less member in the channel // after the delete, there should be one less member in the channel
channelMembers = store.Must(ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id)).([]*model.ChannelMemberHistoryResult) channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id)
require.Nil(t, err)
assert.Len(t, channelMembers, 1) assert.Len(t, channelMembers, 1)
assert.Equal(t, user2.Id, channelMembers[0].UserId) assert.Equal(t, user2.Id, channelMembers[0].UserId)
} }

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

@@ -1236,22 +1236,22 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
require.Len(t, channelMembers, 1) require.Len(t, channelMembers, 1)
// Adding Channel (ChannelMemberHistory) should stop returning result // Adding Channel (ChannelMemberHistory) should stop returning result
res = <-ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()) err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis())
require.Nil(t, res.Err) require.Nil(t, err)
channelMembers, err = ss.Group().ChannelMembersToAdd(0) channelMembers, err = ss.Group().ChannelMembersToAdd(0)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelMembers, 0) require.Len(t, channelMembers, 0)
// Leaving Channel (ChannelMemberHistory) should still not return result // Leaving Channel (ChannelMemberHistory) should still not return result
res = <-ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis()) err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis())
require.Nil(t, res.Err) require.Nil(t, err)
channelMembers, err = ss.Group().ChannelMembersToAdd(0) channelMembers, err = ss.Group().ChannelMembersToAdd(0)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelMembers, 0) require.Len(t, channelMembers, 0)
// Purging ChannelMemberHistory re-returns the result // Purging ChannelMemberHistory re-returns the result
res = <-ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis()+1, 100) _, err = ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis()+1, 100)
require.Nil(t, res.Err) require.Nil(t, err)
channelMembers, err = ss.Group().ChannelMembersToAdd(0) channelMembers, err = ss.Group().ChannelMembersToAdd(0)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelMembers, 1) require.Len(t, channelMembers, 1)

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

@@ -5,7 +5,7 @@
package mocks package mocks
import mock "github.com/stretchr/testify/mock" import mock "github.com/stretchr/testify/mock"
import store "github.com/mattermost/mattermost-server/store" import model "github.com/mattermost/mattermost-server/model"
// ChannelMemberHistoryStore is an autogenerated mock type for the ChannelMemberHistoryStore type // ChannelMemberHistoryStore is an autogenerated mock type for the ChannelMemberHistoryStore type
type ChannelMemberHistoryStore struct { type ChannelMemberHistoryStore struct {
@@ -13,31 +13,40 @@ type ChannelMemberHistoryStore struct {
} }
// GetUsersInChannelDuring provides a mock function with given fields: startTime, endTime, channelId // GetUsersInChannelDuring provides a mock function with given fields: startTime, endTime, channelId
func (_m *ChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) store.StoreChannel { func (_m *ChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, *model.AppError) {
ret := _m.Called(startTime, endTime, channelId) ret := _m.Called(startTime, endTime, channelId)
var r0 store.StoreChannel var r0 []*model.ChannelMemberHistoryResult
if rf, ok := ret.Get(0).(func(int64, int64, string) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(int64, int64, string) []*model.ChannelMemberHistoryResult); ok {
r0 = rf(startTime, endTime, channelId) r0 = rf(startTime, endTime, channelId)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).([]*model.ChannelMemberHistoryResult)
} }
} }
return r0 var r1 *model.AppError
if rf, ok := ret.Get(1).(func(int64, int64, string) *model.AppError); ok {
r1 = rf(startTime, endTime, channelId)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
} }
// LogJoinEvent provides a mock function with given fields: userId, channelId, joinTime // LogJoinEvent provides a mock function with given fields: userId, channelId, joinTime
func (_m *ChannelMemberHistoryStore) LogJoinEvent(userId string, channelId string, joinTime int64) store.StoreChannel { func (_m *ChannelMemberHistoryStore) LogJoinEvent(userId string, channelId string, joinTime int64) *model.AppError {
ret := _m.Called(userId, channelId, joinTime) ret := _m.Called(userId, channelId, joinTime)
var r0 store.StoreChannel var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string, string, int64) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, string, int64) *model.AppError); ok {
r0 = rf(userId, channelId, joinTime) r0 = rf(userId, channelId, joinTime)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).(*model.AppError)
} }
} }
@@ -45,15 +54,15 @@ func (_m *ChannelMemberHistoryStore) LogJoinEvent(userId string, channelId strin
} }
// LogLeaveEvent provides a mock function with given fields: userId, channelId, leaveTime // LogLeaveEvent provides a mock function with given fields: userId, channelId, leaveTime
func (_m *ChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) store.StoreChannel { func (_m *ChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) *model.AppError {
ret := _m.Called(userId, channelId, leaveTime) ret := _m.Called(userId, channelId, leaveTime)
var r0 store.StoreChannel var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string, string, int64) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(string, string, int64) *model.AppError); ok {
r0 = rf(userId, channelId, leaveTime) r0 = rf(userId, channelId, leaveTime)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).(*model.AppError)
} }
} }
@@ -61,17 +70,24 @@ func (_m *ChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId stri
} }
// PermanentDeleteBatch provides a mock function with given fields: endTime, limit // PermanentDeleteBatch provides a mock function with given fields: endTime, limit
func (_m *ChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) store.StoreChannel { func (_m *ChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, *model.AppError) {
ret := _m.Called(endTime, limit) ret := _m.Called(endTime, limit)
var r0 store.StoreChannel var r0 int64
if rf, ok := ret.Get(0).(func(int64, int64) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(int64, int64) int64); ok {
r0 = rf(endTime, limit) r0 = rf(endTime, limit)
} else { } else {
if ret.Get(0) != nil { r0 = ret.Get(0).(int64)
r0 = ret.Get(0).(store.StoreChannel) }
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(int64, int64) *model.AppError); ok {
r1 = rf(endTime, limit)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
} }
} }
return r0 return r0, r1
} }