MM-33746 Add TotalMsgCountRoot and MsgCountRoot columns (#17150)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
ee3f986da0
Коммит
ab5925c4de
@@ -320,6 +320,10 @@ jobs:
|
||||
mattermost/mattermost-build-server:20201119_golang-1.15.5 \
|
||||
bash -c "ulimit -n 8096; make ARGS='version' run-cli && make MM_SQLSETTINGS_DATASOURCE='postgres://mmuser:mostest@postgres:5432/latest?sslmode=disable&connect_timeout=10' ARGS='version' run-cli"
|
||||
|
||||
echo "Ignoring known mismatch: ChannelMembers.MsgCountRoot"
|
||||
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d migrated'
|
||||
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d latest'
|
||||
|
||||
echo "Generating dump"
|
||||
docker-compose --no-ansi exec -T postgres pg_dump --schema-only -d migrated -U mmuser > migrated.sql
|
||||
docker-compose --no-ansi exec -T postgres pg_dump --schema-only -d latest -U mmuser > latest.sql
|
||||
@@ -349,9 +353,13 @@ jobs:
|
||||
mattermost/mattermost-build-server:20201119_golang-1.15.5 \
|
||||
bash -c "ulimit -n 8096; make ARGS='version' run-cli && make MM_SQLSETTINGS_DATASOURCE='mmuser:mostest@tcp(mysql:3306)/latest?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s' ARGS='version' run-cli"
|
||||
|
||||
|
||||
echo "Ignoring known MySQL mismatch: ChannelMembers.SchemeGuest"
|
||||
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||
echo "Ignoring known MySQL mismatch: ChannelMembers.MentionCountRoot"
|
||||
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
||||
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
||||
|
||||
echo "Generating dump"
|
||||
docker-compose --no-ansi exec -T mysql mysqldump --skip-opt --no-data --compact -u root -pmostest migrated > migrated.sql
|
||||
|
||||
@@ -1871,6 +1871,7 @@ func (a *App) GetChannelUnread(channelID, userID string) (*model.ChannelUnread,
|
||||
|
||||
if channelUnread.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_MARK_UNREAD_MENTION {
|
||||
channelUnread.MsgCount = 0
|
||||
channelUnread.MsgCountRoot = 0
|
||||
}
|
||||
|
||||
return channelUnread, nil
|
||||
|
||||
@@ -1411,7 +1411,7 @@ func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *m
|
||||
|
||||
if channel.Type == model.CHANNEL_DIRECT {
|
||||
// In a DM channel, every post made by the other user is a mention
|
||||
count, nErr := a.Srv().Store.Channel().CountPostsAfter(post.ChannelId, post.CreateAt-1, channel.GetOtherUserIdForDM(user.Id))
|
||||
count, _, nErr := a.Srv().Store.Channel().CountPostsAfter(post.ChannelId, post.CreateAt-1, channel.GetOtherUserIdForDM(user.Id))
|
||||
if nErr != nil {
|
||||
return 0, model.NewAppError("countMentionsFromPost", "app.channel.count_posts_since.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -1133,12 +1133,14 @@ func (a *App) AddTeamMemberByInviteId(inviteId, userID string) (*model.TeamMembe
|
||||
|
||||
func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.AppError) {
|
||||
channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamID, userID)
|
||||
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var teamUnread = &model.TeamUnread{
|
||||
MsgCount: 0,
|
||||
MsgCountRoot: 0,
|
||||
MentionCount: 0,
|
||||
TeamId: teamID,
|
||||
}
|
||||
@@ -1148,6 +1150,7 @@ func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.Ap
|
||||
|
||||
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||
teamUnread.MsgCount += cu.MsgCount
|
||||
teamUnread.MsgCountRoot += cu.MsgCountRoot
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1677,6 +1680,7 @@ func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string) ([]*mod
|
||||
|
||||
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||
tu.MsgCount += cu.MsgCount
|
||||
tu.MsgCountRoot += cu.MsgCountRoot
|
||||
}
|
||||
|
||||
return tu
|
||||
@@ -1689,6 +1693,7 @@ func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string) ([]*mod
|
||||
} else {
|
||||
membersMap[id] = unreads(data[i], &model.TeamUnread{
|
||||
MsgCount: 0,
|
||||
MsgCountRoot: 0,
|
||||
MentionCount: 0,
|
||||
TeamId: id,
|
||||
})
|
||||
|
||||
@@ -34,24 +34,25 @@ const (
|
||||
)
|
||||
|
||||
type Channel struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
TeamId string `json:"team_id"`
|
||||
Type string `json:"type"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Name string `json:"name"`
|
||||
Header string `json:"header"`
|
||||
Purpose string `json:"purpose"`
|
||||
LastPostAt int64 `json:"last_post_at"`
|
||||
TotalMsgCount int64 `json:"total_msg_count"`
|
||||
ExtraUpdateAt int64 `json:"extra_update_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
SchemeId *string `json:"scheme_id"`
|
||||
Props map[string]interface{} `json:"props" db:"-"`
|
||||
GroupConstrained *bool `json:"group_constrained"`
|
||||
Shared *bool `json:"shared"`
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
TeamId string `json:"team_id"`
|
||||
Type string `json:"type"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Name string `json:"name"`
|
||||
Header string `json:"header"`
|
||||
Purpose string `json:"purpose"`
|
||||
LastPostAt int64 `json:"last_post_at"`
|
||||
TotalMsgCount int64 `json:"total_msg_count"`
|
||||
ExtraUpdateAt int64 `json:"extra_update_at"`
|
||||
CreatorId string `json:"creator_id"`
|
||||
SchemeId *string `json:"scheme_id"`
|
||||
Props map[string]interface{} `json:"props" db:"-"`
|
||||
GroupConstrained *bool `json:"group_constrained"`
|
||||
Shared *bool `json:"shared"`
|
||||
TotalMsgCountRoot int64 `json:"total_msg_count_root"`
|
||||
}
|
||||
|
||||
type ChannelWithTeamData struct {
|
||||
|
||||
@@ -14,11 +14,12 @@ import (
|
||||
|
||||
type ChannelCounts struct {
|
||||
Counts map[string]int64 `json:"counts"`
|
||||
CountsRoot map[string]int64 `json:"counts_root"`
|
||||
UpdateTimes map[string]int64 `json:"update_times"`
|
||||
}
|
||||
|
||||
func (o *ChannelCounts) Etag() string {
|
||||
|
||||
// we don't include CountsRoot in ETag calculation, since it's a deriviative
|
||||
ids := []string{}
|
||||
for id := range o.Counts {
|
||||
ids = append(ids, id)
|
||||
|
||||
@@ -27,6 +27,7 @@ type ChannelUnread struct {
|
||||
TeamId string `json:"team_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
NotifyProps StringMap `json:"-"`
|
||||
}
|
||||
@@ -36,6 +37,7 @@ type ChannelUnreadAt struct {
|
||||
UserId string `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
LastViewedAt int64 `json:"last_viewed_at"`
|
||||
NotifyProps StringMap `json:"-"`
|
||||
@@ -54,6 +56,7 @@ type ChannelMember struct {
|
||||
SchemeUser bool `json:"scheme_user"`
|
||||
SchemeAdmin bool `json:"scheme_admin"`
|
||||
ExplicitRoles string `json:"explicit_roles"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
}
|
||||
|
||||
type ChannelMembers []ChannelMember
|
||||
|
||||
@@ -33,6 +33,7 @@ type TeamMember struct {
|
||||
type TeamUnread struct {
|
||||
TeamId string `json:"team_id"`
|
||||
MsgCount int64 `json:"msg_count"`
|
||||
MsgCountRoot int64 `json:"msg_count_root"`
|
||||
MentionCount int64 `json:"mention_count"`
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,12 @@ make ARGS="config set SqlSettings.DataSource 'mmuser:mostest@tcp(localhost:3306)
|
||||
echo "Setting up fresh db"
|
||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
||||
|
||||
echo "Ignoring known MySQL mismatch: ChannelMembers.SchemeGuest"
|
||||
docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||
docker exec mattermost-mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||
for i in "ChannelMembers SchemeGuest" "ChannelMembers MsgCountRoot"; do
|
||||
a=( $i );
|
||||
echo "Ignoring known MySQL mismatch: ${a[0]}.${a[1]}"
|
||||
docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||
docker exec mattermost-mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||
done
|
||||
|
||||
echo "Generating dump"
|
||||
docker exec mattermost-mysql mysqldump --skip-opt --no-data --compact -u root -pmostest migrated > $DUMPDIR/migrated.sql
|
||||
|
||||
@@ -22,6 +22,13 @@ make ARGS="config set SqlSettings.DataSource 'postgres://mmuser:mostest@localhos
|
||||
echo "Setting up fresh db"
|
||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
||||
|
||||
for i in "ChannelMembers MsgCountRoot"; do
|
||||
a=( $i );
|
||||
echo "Ignoring known Postgres mismatch: ${a[0]}.${a[1]}"
|
||||
docker exec mattermost-postgres psql -U mmuser -d migrated -c "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||
docker exec mattermost-postgres psql -U mmuser -d latest -c "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||
done
|
||||
|
||||
echo "Generating dump"
|
||||
docker exec mattermost-postgres pg_dump --schema-only -d migrated -U mmuser > $DUMPDIR/migrated.sql
|
||||
docker exec mattermost-postgres pg_dump --schema-only -d latest -U mmuser > $DUMPDIR/latest.sql
|
||||
|
||||
@@ -625,7 +625,7 @@ func (s *OpenTracingLayerChannelStore) ClearSidebarOnTeamLeave(userId string, te
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, error) {
|
||||
func (s *OpenTracingLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.CountPostsAfter")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
@@ -634,13 +634,13 @@ func (s *OpenTracingLayerChannelStore) CountPostsAfter(channelID string, timesta
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
result, resultVar1, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return result, err
|
||||
return result, resultVar1, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) CreateDirectChannel(userId *model.User, otherUserId *model.User) (*model.Channel, error) {
|
||||
|
||||
@@ -664,21 +664,21 @@ func (s *RetryLayerChannelStore) ClearSidebarOnTeamLeave(userId string, teamID s
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, error) {
|
||||
func (s *RetryLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
result, resultVar1, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
if err == nil {
|
||||
return result, nil
|
||||
return result, resultVar1, nil
|
||||
}
|
||||
if !isRepeatableError(err) {
|
||||
return result, err
|
||||
return result, resultVar1, err
|
||||
}
|
||||
tries++
|
||||
if tries >= 3 {
|
||||
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
||||
return result, err
|
||||
return result, resultVar1, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ type channelMember struct {
|
||||
SchemeUser sql.NullBool
|
||||
SchemeAdmin sql.NullBool
|
||||
SchemeGuest sql.NullBool
|
||||
MsgCountRoot int64
|
||||
}
|
||||
|
||||
func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
||||
@@ -59,6 +60,7 @@ func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
||||
Roles: cm.ExplicitRoles,
|
||||
LastViewedAt: cm.LastViewedAt,
|
||||
MsgCount: cm.MsgCount,
|
||||
MsgCountRoot: cm.MsgCountRoot,
|
||||
MentionCount: cm.MentionCount,
|
||||
NotifyProps: cm.NotifyProps,
|
||||
LastUpdateAt: cm.LastUpdateAt,
|
||||
@@ -86,10 +88,11 @@ type channelMemberWithSchemeRoles struct {
|
||||
ChannelSchemeDefaultGuestRole sql.NullString
|
||||
ChannelSchemeDefaultUserRole sql.NullString
|
||||
ChannelSchemeDefaultAdminRole sql.NullString
|
||||
MsgCountRoot int64
|
||||
}
|
||||
|
||||
func channelMemberSliceColumns() []string {
|
||||
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MentionCount", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
|
||||
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MsgCountRoot", "MentionCount", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
|
||||
}
|
||||
|
||||
func channelMemberToSlice(member *model.ChannelMember) []interface{} {
|
||||
@@ -99,6 +102,7 @@ func channelMemberToSlice(member *model.ChannelMember) []interface{} {
|
||||
resultSlice = append(resultSlice, member.ExplicitRoles)
|
||||
resultSlice = append(resultSlice, member.LastViewedAt)
|
||||
resultSlice = append(resultSlice, member.MsgCount)
|
||||
resultSlice = append(resultSlice, member.MsgCountRoot)
|
||||
resultSlice = append(resultSlice, member.MentionCount)
|
||||
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
|
||||
resultSlice = append(resultSlice, member.LastUpdateAt)
|
||||
@@ -230,6 +234,7 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
|
||||
Roles: strings.Join(rolesResult.roles, " "),
|
||||
LastViewedAt: db.LastViewedAt,
|
||||
MsgCount: db.MsgCount,
|
||||
MsgCountRoot: db.MsgCountRoot,
|
||||
MentionCount: db.MentionCount,
|
||||
NotifyProps: db.NotifyProps,
|
||||
LastUpdateAt: db.LastUpdateAt,
|
||||
@@ -712,7 +717,10 @@ func (s SqlChannelStore) GetChannelUnread(channelId, userId string) (*model.Chan
|
||||
var unreadChannel model.ChannelUnread
|
||||
err := s.GetReplica().SelectOne(&unreadChannel,
|
||||
`SELECT
|
||||
Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
|
||||
Channels.TeamId TeamId, Channels.Id ChannelId,
|
||||
(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount,
|
||||
(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot,
|
||||
ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
|
||||
FROM
|
||||
Channels, ChannelMembers
|
||||
WHERE
|
||||
@@ -1181,23 +1189,25 @@ func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds
|
||||
}
|
||||
|
||||
type channelIdWithCountAndUpdateAt struct {
|
||||
Id string
|
||||
TotalMsgCount int64
|
||||
UpdateAt int64
|
||||
Id string
|
||||
TotalMsgCount int64
|
||||
TotalMsgCountRoot int64
|
||||
UpdateAt int64
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, error) {
|
||||
var data []channelIdWithCountAndUpdateAt
|
||||
_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
|
||||
_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, TotalMsgCountRoot, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get channels count with teamId=%s and userId=%s", teamId, userId)
|
||||
}
|
||||
|
||||
counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)}
|
||||
counts := &model.ChannelCounts{Counts: make(map[string]int64), CountsRoot: make(map[string]int64), UpdateTimes: make(map[string]int64)}
|
||||
for i := range data {
|
||||
v := data[i]
|
||||
counts.Counts[v.Id] = v.TotalMsgCount
|
||||
counts.CountsRoot[v.Id] = v.TotalMsgCountRoot
|
||||
counts.UpdateTimes[v.Id] = v.UpdateAt
|
||||
}
|
||||
|
||||
@@ -2061,12 +2071,13 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
props["UserId"] = userId
|
||||
|
||||
var lastPostAtTimes []struct {
|
||||
Id string
|
||||
LastPostAt int64
|
||||
TotalMsgCount int64
|
||||
Id string
|
||||
LastPostAt int64
|
||||
TotalMsgCount int64
|
||||
TotalMsgCountRoot int64
|
||||
}
|
||||
|
||||
query := `SELECT Id, LastPostAt, TotalMsgCount FROM Channels WHERE Id IN ` + keys
|
||||
query := `SELECT Id, LastPostAt, TotalMsgCount, TotalMsgCountRoot FROM Channels WHERE Id IN ` + keys
|
||||
// TODO: use a CTE for mysql too when version 8 becomes the minimum supported version.
|
||||
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
||||
query = `WITH c AS ( ` + query + `),
|
||||
@@ -2076,6 +2087,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
SET
|
||||
MentionCount = 0,
|
||||
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
||||
MsgCountRoot = greatest(cm.MsgCountRoot, c.TotalMsgCountRoot),
|
||||
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
||||
LastUpdateAt = greatest(cm.LastViewedAt, c.LastPostAt)
|
||||
FROM c
|
||||
@@ -2106,6 +2118,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
}
|
||||
|
||||
msgCountQuery := ""
|
||||
msgCountQueryRoot := ""
|
||||
lastViewedQuery := ""
|
||||
|
||||
for index, t := range lastPostAtTimes {
|
||||
@@ -2114,6 +2127,9 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
|
||||
msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
|
||||
|
||||
props["msgCountRoot"+strconv.Itoa(index)] = t.TotalMsgCountRoot
|
||||
msgCountQueryRoot += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCountRoot, :msgCountRoot%d) ", index, index)
|
||||
|
||||
props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
|
||||
lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
|
||||
|
||||
@@ -2125,6 +2141,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
SET
|
||||
MentionCount = 0,
|
||||
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
||||
MsgCountRoot = CASE ChannelId ` + msgCountQueryRoot + ` END,
|
||||
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
||||
LastUpdateAt = LastViewedAt
|
||||
WHERE
|
||||
@@ -2142,8 +2159,8 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
||||
}
|
||||
|
||||
// CountPostsAfter returns the number of posts in the given channel created after but not including the given timestamp. If given a non-empty user ID, only counts posts made by that user.
|
||||
func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, userId string) (int, error) {
|
||||
joinLeavePostTypes, params := MapStringsToQueryParams([]string{
|
||||
func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, userId string) (int, int, error) {
|
||||
joinLeavePostTypes := []string{
|
||||
// These types correspond to the ones checked by Post.IsJoinLeaveMessage
|
||||
model.POST_JOIN_LEAVE,
|
||||
model.POST_ADD_REMOVE,
|
||||
@@ -2155,31 +2172,25 @@ func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, user
|
||||
model.POST_REMOVE_FROM_CHANNEL,
|
||||
model.POST_ADD_TO_TEAM,
|
||||
model.POST_REMOVE_FROM_TEAM,
|
||||
}, "PostType")
|
||||
|
||||
query := `
|
||||
SELECT count(*)
|
||||
FROM Posts
|
||||
WHERE
|
||||
ChannelId = :ChannelId
|
||||
AND CreateAt > :CreateAt
|
||||
AND Type NOT IN ` + joinLeavePostTypes + `
|
||||
AND DeleteAt = 0
|
||||
`
|
||||
|
||||
params["ChannelId"] = channelId
|
||||
params["CreateAt"] = timestamp
|
||||
}
|
||||
query := s.getQueryBuilder().Select("count(*)").From("Posts").Where(sq.Eq{"ChannelId": channelId}).Where(sq.Gt{"CreateAt": timestamp}).Where(sq.NotEq{"Type": joinLeavePostTypes}).Where(sq.Eq{"DeleteAt": 0})
|
||||
|
||||
if userId != "" {
|
||||
query += " AND UserId = :UserId"
|
||||
params["UserId"] = userId
|
||||
query = query.Where(sq.Eq{"UserId": userId})
|
||||
}
|
||||
sql, args, _ := query.ToSql()
|
||||
|
||||
unread, err := s.GetReplica().SelectInt(query, params)
|
||||
unread, err := s.GetReplica().SelectInt(sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to count Posts")
|
||||
return 0, 0, errors.Wrap(err, "failed to count Posts")
|
||||
}
|
||||
return int(unread), nil
|
||||
sql2, args2, _ := query.Where(sq.Eq{"RootId": ""}).ToSql()
|
||||
|
||||
unreadRoot, err := s.GetReplica().SelectInt(sql2, args2...)
|
||||
if err != nil {
|
||||
return 0, 0, errors.Wrap(err, "failed to count root Posts")
|
||||
}
|
||||
return int(unread), int(unreadRoot), nil
|
||||
}
|
||||
|
||||
// UpdateLastViewedAtPost updates a ChannelMember as if the user last read the channel at the time of the given post.
|
||||
@@ -2196,18 +2207,19 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
||||
}
|
||||
}
|
||||
|
||||
unread, err := s.CountPostsAfter(unreadPost.ChannelId, unreadDate, "")
|
||||
unread, unreadRoot, err := s.CountPostsAfter(unreadPost.ChannelId, unreadDate, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := map[string]interface{}{
|
||||
"mentions": mentionCount,
|
||||
"unreadCount": unread,
|
||||
"lastViewedAt": unreadDate,
|
||||
"userId": userID,
|
||||
"channelId": unreadPost.ChannelId,
|
||||
"updatedAt": model.GetMillis(),
|
||||
"mentions": mentionCount,
|
||||
"unreadCount": unread,
|
||||
"unreadCountRoot": unreadRoot,
|
||||
"lastViewedAt": unreadDate,
|
||||
"userId": userID,
|
||||
"channelId": unreadPost.ChannelId,
|
||||
"updatedAt": model.GetMillis(),
|
||||
}
|
||||
|
||||
// msg count uses the value from channels to prevent counting on older channels where no. of messages can be high.
|
||||
@@ -2218,6 +2230,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
||||
SET
|
||||
MentionCount = :mentions,
|
||||
MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
|
||||
MsgCountRoot = (SELECT TotalMsgCountRoot FROM Channels WHERE ID = :channelId) - :unreadCountRoot,
|
||||
LastViewedAt = :lastViewedAt,
|
||||
LastUpdateAt = :updatedAt
|
||||
WHERE
|
||||
@@ -2235,6 +2248,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
||||
cm.UserId UserId,
|
||||
cm.ChannelId ChannelId,
|
||||
cm.MsgCount MsgCount,
|
||||
cm.MsgCountRoot MsgCountRoot,
|
||||
cm.MentionCount MentionCount,
|
||||
cm.LastViewedAt LastViewedAt,
|
||||
cm.NotifyProps NotifyProps
|
||||
|
||||
@@ -917,6 +917,7 @@ func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.Chan
|
||||
"ChannelMembers.UserId",
|
||||
"ChannelMembers.LastViewedAt",
|
||||
"ChannelMembers.MsgCount",
|
||||
"ChannelMembers.MsgCountRoot",
|
||||
"ChannelMembers.MentionCount",
|
||||
"ChannelMembers.NotifyProps",
|
||||
"ChannelMembers.LastUpdateAt",
|
||||
|
||||
@@ -112,6 +112,7 @@ func (s *SqlPostStore) createIndexesIfNotExists() {
|
||||
|
||||
func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, error) {
|
||||
channelNewPosts := make(map[string]int)
|
||||
channelNewRootPosts := make(map[string]int)
|
||||
maxDateNewPosts := make(map[string]int64)
|
||||
rootIds := make(map[string]int)
|
||||
maxDateRootIds := make(map[string]int64)
|
||||
@@ -125,8 +126,7 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
||||
return nil, idx, err
|
||||
}
|
||||
|
||||
currentChannelCount, ok := channelNewPosts[post.ChannelId]
|
||||
if !ok {
|
||||
if currentChannelCount, ok := channelNewPosts[post.ChannelId]; !ok {
|
||||
if post.IsJoinLeaveMessage() {
|
||||
channelNewPosts[post.ChannelId] = 0
|
||||
} else {
|
||||
@@ -143,11 +143,21 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
||||
}
|
||||
|
||||
if post.RootId == "" {
|
||||
if currentChannelCount, ok := channelNewRootPosts[post.ChannelId]; !ok {
|
||||
if post.IsJoinLeaveMessage() {
|
||||
channelNewRootPosts[post.ChannelId] = 0
|
||||
} else {
|
||||
channelNewRootPosts[post.ChannelId] = 1
|
||||
}
|
||||
} else {
|
||||
if !post.IsJoinLeaveMessage() {
|
||||
channelNewRootPosts[post.ChannelId] = currentChannelCount + 1
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
currentRootCount, ok := rootIds[post.RootId]
|
||||
if !ok {
|
||||
if currentRootCount, ok := rootIds[post.RootId]; !ok {
|
||||
rootIds[post.RootId] = 1
|
||||
maxDateRootIds[post.RootId] = post.CreateAt
|
||||
} else {
|
||||
@@ -188,7 +198,9 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
||||
}
|
||||
|
||||
for channelId, count := range channelNewPosts {
|
||||
if _, err = s.GetMaster().Exec("UPDATE Channels SET LastPostAt = GREATEST(:LastPostAt, LastPostAt), TotalMsgCount = TotalMsgCount + :Count WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": maxDateNewPosts[channelId], "ChannelId": channelId, "Count": count}); err != nil {
|
||||
countRoot := channelNewRootPosts[channelId]
|
||||
|
||||
if _, err = s.GetMaster().Exec("UPDATE Channels SET LastPostAt = GREATEST(:LastPostAt, LastPostAt), TotalMsgCount = TotalMsgCount + :Count, TotalMsgCountRoot = TotalMsgCountRoot + :CountRoot WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": maxDateNewPosts[channelId], "ChannelId": channelId, "Count": count, "CountRoot": countRoot}); err != nil {
|
||||
mlog.Warn("Error updating Channel LastPostAt.", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1177,7 +1177,7 @@ func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage
|
||||
// for all the channels in all the teams except the excluded ones.
|
||||
func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) ([]*model.ChannelUnread, error) {
|
||||
query, args, err := s.getQueryBuilder().
|
||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
||||
From("Channels").
|
||||
Join("ChannelMembers ON Id = ChannelId").
|
||||
Where(sq.Eq{"UserId": userId, "DeleteAt": 0}).
|
||||
@@ -1199,7 +1199,7 @@ func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string)
|
||||
// GetChannelUnreadsForTeam returns unreads msg count, mention counts and notifyProps for all the channels in a single team.
|
||||
func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) ([]*model.ChannelUnread, error) {
|
||||
query, args, err := s.getQueryBuilder().
|
||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
||||
From("Channels").
|
||||
Join("ChannelMembers ON Id = ChannelId").
|
||||
Where(sq.Eq{"UserId": userId, "TeamId": teamId, "DeleteAt": 0}).ToSql()
|
||||
|
||||
@@ -1011,6 +1011,57 @@ func upgradeDatabaseToVersion535(sqlStore *SqlStore) {
|
||||
|
||||
sqlStore.CreateColumnIfNotExists("SidebarCategories", "Collapsed", "tinyint(1)", "boolean", "0")
|
||||
|
||||
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "TotalMsgCountRoot", "bigint", "bigint")
|
||||
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "LastRootPostAt", "bigint", "bigint")
|
||||
defer sqlStore.RemoveColumnIfExists("Channels", "LastRootPostAt")
|
||||
|
||||
// note: setting default 0 on pre-5.0 tables causes test-db-migration script to fail, so this column will be added to ignore list
|
||||
sqlStore.CreateColumnIfNotExists("ChannelMembers", "MsgCountRoot", "bigint", "bigint", "0")
|
||||
sqlStore.AlterColumnDefaultIfExists("ChannelMembers", "MsgCountRoot", model.NewString("0"), model.NewString("0"))
|
||||
|
||||
forceIndex := ""
|
||||
if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
|
||||
forceIndex = "FORCE INDEX(idx_posts_channel_id)"
|
||||
}
|
||||
totalMsgCountRootCTE := `
|
||||
SELECT Channels.Id channelid, COALESCE(COUNT(*),0) newcount, COALESCE(MAX(Posts.CreateAt), 0) as lastpost
|
||||
FROM Channels
|
||||
LEFT JOIN Posts ` + forceIndex + ` ON Channels.Id = Posts.ChannelId
|
||||
WHERE Posts.RootId = ''
|
||||
GROUP BY Channels.Id
|
||||
`
|
||||
channelsCTE := "SELECT TotalMsgCountRoot, Id, LastRootPostAt from Channels"
|
||||
updateChannels := `
|
||||
WITH q AS (` + totalMsgCountRootCTE + `)
|
||||
UPDATE Channels SET TotalMsgCountRoot = q.newcount, LastRootPostAt=q.lastpost
|
||||
FROM q where q.channelid=Channels.Id;
|
||||
`
|
||||
updateChannelMembers := `
|
||||
WITH q as (` + channelsCTE + `)
|
||||
UPDATE ChannelMembers CM SET MsgCountRoot=TotalMsgCountRoot
|
||||
FROM q WHERE q.id=CM.ChannelId AND LastViewedAt >= q.lastrootpostat;
|
||||
`
|
||||
if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
|
||||
updateChannels = `
|
||||
UPDATE Channels
|
||||
INNER Join (` + totalMsgCountRootCTE + `) as q
|
||||
ON q.channelid=Channels.Id
|
||||
SET TotalMsgCountRoot = q.newcount, LastRootPostAt=q.lastpost;
|
||||
`
|
||||
updateChannelMembers = `
|
||||
UPDATE ChannelMembers CM
|
||||
INNER JOIN (` + channelsCTE + `) as q
|
||||
ON q.id=CM.ChannelId and LastViewedAt >= q.lastrootpostat
|
||||
SET MsgCountRoot=TotalMsgCountRoot
|
||||
`
|
||||
}
|
||||
if _, err := sqlStore.GetMaster().Exec(updateChannels); err != nil {
|
||||
mlog.Error("Error updating Channels table", mlog.Err(err))
|
||||
}
|
||||
if _, err := sqlStore.GetMaster().Exec(updateChannelMembers); err != nil {
|
||||
mlog.Error("Error updating ChannelMembers table", mlog.Err(err))
|
||||
}
|
||||
|
||||
// saveSchemaVersion(sqlStore, Version5350)
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ package sqlstore
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/store"
|
||||
)
|
||||
|
||||
@@ -103,3 +105,139 @@ func TestSaveSchemaVersion(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
func createChannelMemberWithLastViewAt(ss store.Store, channelId, userId string, lastViewAt int64) *model.ChannelMember {
|
||||
m := model.ChannelMember{}
|
||||
m.ChannelId = channelId
|
||||
m.UserId = userId
|
||||
m.LastViewedAt = lastViewAt
|
||||
m.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||
cm, _ := ss.Channel().SaveMember(&m)
|
||||
return cm
|
||||
}
|
||||
func createPostWithTimestamp(ss store.Store, channelId, userId, rootId, parentId string, timestamp int64) *model.Post {
|
||||
m := model.Post{}
|
||||
m.CreateAt = timestamp
|
||||
m.ChannelId = channelId
|
||||
m.UserId = userId
|
||||
m.RootId = rootId
|
||||
m.ParentId = parentId
|
||||
m.Message = "zz" + model.NewId() + "b"
|
||||
p, _ := ss.Post().Save(&m)
|
||||
return p
|
||||
}
|
||||
|
||||
func createChannelWithLastPostAt(ss store.Store, teamId, creatorId string, lastPostAt, msgCount, rootCount int64) (*model.Channel, error) {
|
||||
m := model.Channel{}
|
||||
m.TeamId = teamId
|
||||
m.TotalMsgCount = msgCount
|
||||
m.TotalMsgCountRoot = rootCount
|
||||
m.LastPostAt = lastPostAt
|
||||
m.CreatorId = creatorId
|
||||
m.DisplayName = "Name"
|
||||
m.Name = "zz" + model.NewId() + "b"
|
||||
m.Type = model.CHANNEL_OPEN
|
||||
return ss.Channel().Save(&m, -1)
|
||||
}
|
||||
func TestMsgCountRootMigration(t *testing.T) {
|
||||
type TestCaseChannel struct {
|
||||
Name string
|
||||
PostTimes []int64
|
||||
ReplyTimes []int64
|
||||
MembershipsLastViewAt []int64
|
||||
ExpectedMembershipMsgCountRoot []int64
|
||||
}
|
||||
type TestTableEntry struct {
|
||||
name string
|
||||
data []TestCaseChannel
|
||||
}
|
||||
testTable := []TestTableEntry{
|
||||
{
|
||||
name: "test1",
|
||||
data: []TestCaseChannel{
|
||||
{
|
||||
Name: "channel with one post",
|
||||
PostTimes: []int64{1000},
|
||||
ReplyTimes: []int64{0},
|
||||
MembershipsLastViewAt: []int64{1},
|
||||
ExpectedMembershipMsgCountRoot: []int64{0},
|
||||
},
|
||||
{
|
||||
Name: "channel with one post, read",
|
||||
PostTimes: []int64{1000},
|
||||
ReplyTimes: []int64{0},
|
||||
MembershipsLastViewAt: []int64{1000},
|
||||
ExpectedMembershipMsgCountRoot: []int64{1},
|
||||
},
|
||||
{
|
||||
Name: "with one reply, viewed after 2nd root",
|
||||
PostTimes: []int64{1000, 2000, 3000, 4000},
|
||||
ReplyTimes: []int64{1001, 0, 0, 0},
|
||||
MembershipsLastViewAt: []int64{2001},
|
||||
ExpectedMembershipMsgCountRoot: []int64{0},
|
||||
},
|
||||
{
|
||||
Name: "two replies, 3 memberships",
|
||||
PostTimes: []int64{1000, 2000, 3000},
|
||||
ReplyTimes: []int64{1001, 2001, 0},
|
||||
MembershipsLastViewAt: []int64{2000, 5000, 0},
|
||||
ExpectedMembershipMsgCountRoot: []int64{0, 3, 0},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
sqlStore := ss.(*SqlStore)
|
||||
team := createTeam(ss)
|
||||
for _, testChannel := range testCase.data {
|
||||
t.Run(testChannel.Name, func(t *testing.T) {
|
||||
lastPostAt := int64(0)
|
||||
for i := range testChannel.PostTimes {
|
||||
if testChannel.PostTimes[i] > lastPostAt {
|
||||
lastPostAt = testChannel.PostTimes[i]
|
||||
}
|
||||
if testChannel.ReplyTimes[i] > lastPostAt {
|
||||
lastPostAt = testChannel.ReplyTimes[i]
|
||||
}
|
||||
}
|
||||
channel, err := createChannelWithLastPostAt(ss, team.Id, model.NewId(), lastPostAt, int64(len(testChannel.PostTimes)+len(testChannel.ReplyTimes)), int64(len(testChannel.PostTimes)))
|
||||
require.NoError(t, err)
|
||||
var userIds []string
|
||||
for _, md := range testChannel.MembershipsLastViewAt {
|
||||
user := createUser(ss)
|
||||
userIds = append(userIds, user.Id)
|
||||
require.NotNil(t, user)
|
||||
cm := createChannelMemberWithLastViewAt(ss, channel.Id, user.Id, md)
|
||||
require.NotNil(t, cm)
|
||||
}
|
||||
for i, pt := range testChannel.PostTimes {
|
||||
rt := testChannel.ReplyTimes[i]
|
||||
post := createPostWithTimestamp(ss, channel.Id, model.NewId(), "", "", pt)
|
||||
require.NotNil(t, post)
|
||||
if rt > 0 {
|
||||
reply := createPostWithTimestamp(ss, channel.Id, model.NewId(), post.Id, post.Id, rt)
|
||||
require.NotNil(t, reply)
|
||||
}
|
||||
}
|
||||
|
||||
upgradeDatabaseToVersion535(sqlStore)
|
||||
|
||||
members, err := ss.Channel().GetMembersByIds(channel.Id, userIds)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, m := range *members {
|
||||
for i, uid := range userIds {
|
||||
if m.UserId == uid {
|
||||
assert.Equal(t, testChannel.ExpectedMembershipMsgCountRoot[i], m.MsgCountRoot)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ type ChannelStore interface {
|
||||
PermanentDeleteMembersByChannel(channelID string) error
|
||||
UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error)
|
||||
UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error)
|
||||
CountPostsAfter(channelID string, timestamp int64, userId string) (int, error)
|
||||
CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error)
|
||||
IncrementMentionCount(channelID string, userId string, updateThreads bool) error
|
||||
AnalyticsTypeCount(teamID string, channelType string) (int64, error)
|
||||
GetMembersForUser(teamID string, userId string) (*model.ChannelMembers, error)
|
||||
|
||||
@@ -327,20 +327,20 @@ func testGetChannelUnread(t *testing.T, ss store.Store) {
|
||||
notifyPropsModel := model.GetDefaultChannelNotifyProps()
|
||||
|
||||
// Setup Channel 1
|
||||
c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Downtown", Type: model.CHANNEL_OPEN, TotalMsgCount: 100}
|
||||
c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Downtown", Type: model.CHANNEL_OPEN, TotalMsgCount: 100, TotalMsgCountRoot: 99}
|
||||
_, nErr = ss.Channel().Save(c1, -1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: notifyPropsModel, MsgCount: 90}
|
||||
cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MsgCountRoot: 80}
|
||||
_, err := ss.Channel().SaveMember(cm1)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Channel 2
|
||||
c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Cultural", Type: model.CHANNEL_OPEN, TotalMsgCount: 100}
|
||||
c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Cultural", Type: model.CHANNEL_OPEN, TotalMsgCount: 100, TotalMsgCountRoot: 100}
|
||||
_, nErr = ss.Channel().Save(c2, -1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MentionCount: 5}
|
||||
cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MsgCountRoot: 90, MentionCount: 5}
|
||||
_, err = ss.Channel().SaveMember(cm2)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -353,7 +353,7 @@ func testGetChannelUnread(t *testing.T, ss store.Store) {
|
||||
require.NotNil(t, ch.NotifyProps, "wrong props for channel 1")
|
||||
require.EqualValues(t, 0, ch.MentionCount, "wrong MentionCount for channel 1")
|
||||
require.EqualValues(t, 10, ch.MsgCount, "wrong MsgCount for channel 1")
|
||||
|
||||
require.EqualValues(t, 19, ch.MsgCountRoot, "wrong MsgCountRoot for channel 1")
|
||||
// Check for Channel 2
|
||||
ch2, nErr := ss.Channel().GetChannelUnread(c2.Id, uid)
|
||||
|
||||
@@ -4007,19 +4007,19 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
count, _, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 3, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, userId1)
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, userId1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, userId1)
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, userId1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, count)
|
||||
})
|
||||
@@ -4044,11 +4044,11 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
count, _, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, count)
|
||||
})
|
||||
@@ -4105,19 +4105,19 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
count, _, err := ss.Channel().CountPostsAfter(channelId, p1.CreateAt-1, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 3, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p1.CreateAt, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p5.CreateAt-1, "")
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p5.CreateAt-1, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
|
||||
count, err = ss.Channel().CountPostsAfter(channelId, p5.CreateAt, "")
|
||||
count, _, err = ss.Channel().CountPostsAfter(channelId, p5.CreateAt, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, count)
|
||||
})
|
||||
@@ -6345,9 +6345,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlStore) {
|
||||
|
||||
_, execerr = s.GetMaster().ExecNoTimeout(`
|
||||
INSERT INTO
|
||||
Channels(Id, CreateAt, UpdateAt, DeleteAt, TeamId, Type, DisplayName, Name, Header, Purpose, LastPostAt, TotalMsgCount, ExtraUpdateAt, CreatorId)
|
||||
Channels(Id, CreateAt, UpdateAt, DeleteAt, TeamId, Type, DisplayName, Name, Header, Purpose, LastPostAt, TotalMsgCount, ExtraUpdateAt, CreatorId, TotalMsgCountRoot)
|
||||
VALUES
|
||||
(:Id, :CreateAt, :UpdateAt, :DeleteAt, :TeamId, :Type, :DisplayName, :Name, :Header, :Purpose, :LastPostAt, :TotalMsgCount, :ExtraUpdateAt, :CreatorId);
|
||||
(:Id, :CreateAt, :UpdateAt, :DeleteAt, :TeamId, :Type, :DisplayName, :Name, :Header, :Purpose, :LastPostAt, :TotalMsgCount, :ExtraUpdateAt, :CreatorId, 0);
|
||||
`, map[string]interface{}{
|
||||
"Id": o3.Id,
|
||||
"CreateAt": o3.CreateAt,
|
||||
|
||||
@@ -140,7 +140,7 @@ func (_m *ChannelStore) ClearSidebarOnTeamLeave(userId string, teamID string) er
|
||||
}
|
||||
|
||||
// CountPostsAfter provides a mock function with given fields: channelID, timestamp, userId
|
||||
func (_m *ChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, error) {
|
||||
func (_m *ChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error) {
|
||||
ret := _m.Called(channelID, timestamp, userId)
|
||||
|
||||
var r0 int
|
||||
@@ -150,14 +150,21 @@ func (_m *ChannelStore) CountPostsAfter(channelID string, timestamp int64, userI
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, int64, string) error); ok {
|
||||
var r1 int
|
||||
if rf, ok := ret.Get(1).(func(string, int64, string) int); ok {
|
||||
r1 = rf(channelID, timestamp, userId)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
r1 = ret.Get(1).(int)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(string, int64, string) error); ok {
|
||||
r2 = rf(channelID, timestamp, userId)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// CreateDirectChannel provides a mock function with given fields: userId, otherUserId
|
||||
|
||||
@@ -599,10 +599,10 @@ func (s *TimerLayerChannelStore) ClearSidebarOnTeamLeave(userId string, teamID s
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, error) {
|
||||
func (s *TimerLayerChannelStore) CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
result, resultVar1, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -612,7 +612,7 @@ func (s *TimerLayerChannelStore) CountPostsAfter(channelID string, timestamp int
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.CountPostsAfter", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
return result, resultVar1, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) CreateDirectChannel(userId *model.User, otherUserId *model.User) (*model.Channel, error) {
|
||||
|
||||
Ссылка в новой задаче
Block a user