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 \
|
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"
|
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"
|
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 migrated -U mmuser > migrated.sql
|
||||||
docker-compose --no-ansi exec -T postgres pg_dump --schema-only -d latest -U mmuser > latest.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 \
|
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"
|
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"
|
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 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;"
|
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"
|
echo "Generating dump"
|
||||||
docker-compose --no-ansi exec -T mysql mysqldump --skip-opt --no-data --compact -u root -pmostest migrated > migrated.sql
|
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 {
|
if channelUnread.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_MARK_UNREAD_MENTION {
|
||||||
channelUnread.MsgCount = 0
|
channelUnread.MsgCount = 0
|
||||||
|
channelUnread.MsgCountRoot = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return channelUnread, nil
|
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 {
|
if channel.Type == model.CHANNEL_DIRECT {
|
||||||
// In a DM channel, every post made by the other user is a mention
|
// 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 {
|
if nErr != nil {
|
||||||
return 0, model.NewAppError("countMentionsFromPost", "app.channel.count_posts_since.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
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) {
|
func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.AppError) {
|
||||||
channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamID, userID)
|
channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamID, userID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var teamUnread = &model.TeamUnread{
|
var teamUnread = &model.TeamUnread{
|
||||||
MsgCount: 0,
|
MsgCount: 0,
|
||||||
|
MsgCountRoot: 0,
|
||||||
MentionCount: 0,
|
MentionCount: 0,
|
||||||
TeamId: teamID,
|
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 {
|
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||||
teamUnread.MsgCount += cu.MsgCount
|
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 {
|
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||||
tu.MsgCount += cu.MsgCount
|
tu.MsgCount += cu.MsgCount
|
||||||
|
tu.MsgCountRoot += cu.MsgCountRoot
|
||||||
}
|
}
|
||||||
|
|
||||||
return tu
|
return tu
|
||||||
@@ -1689,6 +1693,7 @@ func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string) ([]*mod
|
|||||||
} else {
|
} else {
|
||||||
membersMap[id] = unreads(data[i], &model.TeamUnread{
|
membersMap[id] = unreads(data[i], &model.TeamUnread{
|
||||||
MsgCount: 0,
|
MsgCount: 0,
|
||||||
|
MsgCountRoot: 0,
|
||||||
MentionCount: 0,
|
MentionCount: 0,
|
||||||
TeamId: id,
|
TeamId: id,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -34,24 +34,25 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Channel struct {
|
type Channel struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
CreateAt int64 `json:"create_at"`
|
CreateAt int64 `json:"create_at"`
|
||||||
UpdateAt int64 `json:"update_at"`
|
UpdateAt int64 `json:"update_at"`
|
||||||
DeleteAt int64 `json:"delete_at"`
|
DeleteAt int64 `json:"delete_at"`
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Header string `json:"header"`
|
Header string `json:"header"`
|
||||||
Purpose string `json:"purpose"`
|
Purpose string `json:"purpose"`
|
||||||
LastPostAt int64 `json:"last_post_at"`
|
LastPostAt int64 `json:"last_post_at"`
|
||||||
TotalMsgCount int64 `json:"total_msg_count"`
|
TotalMsgCount int64 `json:"total_msg_count"`
|
||||||
ExtraUpdateAt int64 `json:"extra_update_at"`
|
ExtraUpdateAt int64 `json:"extra_update_at"`
|
||||||
CreatorId string `json:"creator_id"`
|
CreatorId string `json:"creator_id"`
|
||||||
SchemeId *string `json:"scheme_id"`
|
SchemeId *string `json:"scheme_id"`
|
||||||
Props map[string]interface{} `json:"props" db:"-"`
|
Props map[string]interface{} `json:"props" db:"-"`
|
||||||
GroupConstrained *bool `json:"group_constrained"`
|
GroupConstrained *bool `json:"group_constrained"`
|
||||||
Shared *bool `json:"shared"`
|
Shared *bool `json:"shared"`
|
||||||
|
TotalMsgCountRoot int64 `json:"total_msg_count_root"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelWithTeamData struct {
|
type ChannelWithTeamData struct {
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import (
|
|||||||
|
|
||||||
type ChannelCounts struct {
|
type ChannelCounts struct {
|
||||||
Counts map[string]int64 `json:"counts"`
|
Counts map[string]int64 `json:"counts"`
|
||||||
|
CountsRoot map[string]int64 `json:"counts_root"`
|
||||||
UpdateTimes map[string]int64 `json:"update_times"`
|
UpdateTimes map[string]int64 `json:"update_times"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ChannelCounts) Etag() string {
|
func (o *ChannelCounts) Etag() string {
|
||||||
|
// we don't include CountsRoot in ETag calculation, since it's a deriviative
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
for id := range o.Counts {
|
for id := range o.Counts {
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type ChannelUnread struct {
|
|||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
NotifyProps StringMap `json:"-"`
|
NotifyProps StringMap `json:"-"`
|
||||||
}
|
}
|
||||||
@@ -36,6 +37,7 @@ type ChannelUnreadAt struct {
|
|||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
LastViewedAt int64 `json:"last_viewed_at"`
|
LastViewedAt int64 `json:"last_viewed_at"`
|
||||||
NotifyProps StringMap `json:"-"`
|
NotifyProps StringMap `json:"-"`
|
||||||
@@ -54,6 +56,7 @@ type ChannelMember struct {
|
|||||||
SchemeUser bool `json:"scheme_user"`
|
SchemeUser bool `json:"scheme_user"`
|
||||||
SchemeAdmin bool `json:"scheme_admin"`
|
SchemeAdmin bool `json:"scheme_admin"`
|
||||||
ExplicitRoles string `json:"explicit_roles"`
|
ExplicitRoles string `json:"explicit_roles"`
|
||||||
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelMembers []ChannelMember
|
type ChannelMembers []ChannelMember
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type TeamMember struct {
|
|||||||
type TeamUnread struct {
|
type TeamUnread struct {
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
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"
|
echo "Setting up fresh db"
|
||||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
make ARGS="version --config $TMPDIR/config.json" run-cli
|
||||||
|
|
||||||
echo "Ignoring known MySQL mismatch: ChannelMembers.SchemeGuest"
|
for i in "ChannelMembers SchemeGuest" "ChannelMembers MsgCountRoot"; do
|
||||||
docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
a=( $i );
|
||||||
docker exec mattermost-mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
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"
|
echo "Generating dump"
|
||||||
docker exec mattermost-mysql mysqldump --skip-opt --no-data --compact -u root -pmostest migrated > $DUMPDIR/migrated.sql
|
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"
|
echo "Setting up fresh db"
|
||||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
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"
|
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 migrated -U mmuser > $DUMPDIR/migrated.sql
|
||||||
docker exec mattermost-postgres pg_dump --schema-only -d latest -U mmuser > $DUMPDIR/latest.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
|
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()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.CountPostsAfter")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.CountPostsAfter")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -634,13 +634,13 @@ func (s *OpenTracingLayerChannelStore) CountPostsAfter(channelID string, timesta
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
result, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
result, resultVar1, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
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) {
|
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
|
tries := 0
|
||||||
for {
|
for {
|
||||||
result, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
result, resultVar1, err := s.ChannelStore.CountPostsAfter(channelID, timestamp, userId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result, nil
|
return result, resultVar1, nil
|
||||||
}
|
}
|
||||||
if !isRepeatableError(err) {
|
if !isRepeatableError(err) {
|
||||||
return result, err
|
return result, resultVar1, err
|
||||||
}
|
}
|
||||||
tries++
|
tries++
|
||||||
if tries >= 3 {
|
if tries >= 3 {
|
||||||
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
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
|
SchemeUser sql.NullBool
|
||||||
SchemeAdmin sql.NullBool
|
SchemeAdmin sql.NullBool
|
||||||
SchemeGuest sql.NullBool
|
SchemeGuest sql.NullBool
|
||||||
|
MsgCountRoot int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
||||||
@@ -59,6 +60,7 @@ func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
|||||||
Roles: cm.ExplicitRoles,
|
Roles: cm.ExplicitRoles,
|
||||||
LastViewedAt: cm.LastViewedAt,
|
LastViewedAt: cm.LastViewedAt,
|
||||||
MsgCount: cm.MsgCount,
|
MsgCount: cm.MsgCount,
|
||||||
|
MsgCountRoot: cm.MsgCountRoot,
|
||||||
MentionCount: cm.MentionCount,
|
MentionCount: cm.MentionCount,
|
||||||
NotifyProps: cm.NotifyProps,
|
NotifyProps: cm.NotifyProps,
|
||||||
LastUpdateAt: cm.LastUpdateAt,
|
LastUpdateAt: cm.LastUpdateAt,
|
||||||
@@ -86,10 +88,11 @@ type channelMemberWithSchemeRoles struct {
|
|||||||
ChannelSchemeDefaultGuestRole sql.NullString
|
ChannelSchemeDefaultGuestRole sql.NullString
|
||||||
ChannelSchemeDefaultUserRole sql.NullString
|
ChannelSchemeDefaultUserRole sql.NullString
|
||||||
ChannelSchemeDefaultAdminRole sql.NullString
|
ChannelSchemeDefaultAdminRole sql.NullString
|
||||||
|
MsgCountRoot int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func channelMemberSliceColumns() []string {
|
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{} {
|
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.ExplicitRoles)
|
||||||
resultSlice = append(resultSlice, member.LastViewedAt)
|
resultSlice = append(resultSlice, member.LastViewedAt)
|
||||||
resultSlice = append(resultSlice, member.MsgCount)
|
resultSlice = append(resultSlice, member.MsgCount)
|
||||||
|
resultSlice = append(resultSlice, member.MsgCountRoot)
|
||||||
resultSlice = append(resultSlice, member.MentionCount)
|
resultSlice = append(resultSlice, member.MentionCount)
|
||||||
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
|
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
|
||||||
resultSlice = append(resultSlice, member.LastUpdateAt)
|
resultSlice = append(resultSlice, member.LastUpdateAt)
|
||||||
@@ -230,6 +234,7 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
|
|||||||
Roles: strings.Join(rolesResult.roles, " "),
|
Roles: strings.Join(rolesResult.roles, " "),
|
||||||
LastViewedAt: db.LastViewedAt,
|
LastViewedAt: db.LastViewedAt,
|
||||||
MsgCount: db.MsgCount,
|
MsgCount: db.MsgCount,
|
||||||
|
MsgCountRoot: db.MsgCountRoot,
|
||||||
MentionCount: db.MentionCount,
|
MentionCount: db.MentionCount,
|
||||||
NotifyProps: db.NotifyProps,
|
NotifyProps: db.NotifyProps,
|
||||||
LastUpdateAt: db.LastUpdateAt,
|
LastUpdateAt: db.LastUpdateAt,
|
||||||
@@ -712,7 +717,10 @@ func (s SqlChannelStore) GetChannelUnread(channelId, userId string) (*model.Chan
|
|||||||
var unreadChannel model.ChannelUnread
|
var unreadChannel model.ChannelUnread
|
||||||
err := s.GetReplica().SelectOne(&unreadChannel,
|
err := s.GetReplica().SelectOne(&unreadChannel,
|
||||||
`SELECT
|
`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
|
FROM
|
||||||
Channels, ChannelMembers
|
Channels, ChannelMembers
|
||||||
WHERE
|
WHERE
|
||||||
@@ -1181,23 +1189,25 @@ func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds
|
|||||||
}
|
}
|
||||||
|
|
||||||
type channelIdWithCountAndUpdateAt struct {
|
type channelIdWithCountAndUpdateAt struct {
|
||||||
Id string
|
Id string
|
||||||
TotalMsgCount int64
|
TotalMsgCount int64
|
||||||
UpdateAt int64
|
TotalMsgCountRoot int64
|
||||||
|
UpdateAt int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, error) {
|
func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, error) {
|
||||||
var data []channelIdWithCountAndUpdateAt
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get channels count with teamId=%s and userId=%s", teamId, userId)
|
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 {
|
for i := range data {
|
||||||
v := data[i]
|
v := data[i]
|
||||||
counts.Counts[v.Id] = v.TotalMsgCount
|
counts.Counts[v.Id] = v.TotalMsgCount
|
||||||
|
counts.CountsRoot[v.Id] = v.TotalMsgCountRoot
|
||||||
counts.UpdateTimes[v.Id] = v.UpdateAt
|
counts.UpdateTimes[v.Id] = v.UpdateAt
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2061,12 +2071,13 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
props["UserId"] = userId
|
props["UserId"] = userId
|
||||||
|
|
||||||
var lastPostAtTimes []struct {
|
var lastPostAtTimes []struct {
|
||||||
Id string
|
Id string
|
||||||
LastPostAt int64
|
LastPostAt int64
|
||||||
TotalMsgCount 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.
|
// TODO: use a CTE for mysql too when version 8 becomes the minimum supported version.
|
||||||
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
||||||
query = `WITH c AS ( ` + query + `),
|
query = `WITH c AS ( ` + query + `),
|
||||||
@@ -2076,6 +2087,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
SET
|
SET
|
||||||
MentionCount = 0,
|
MentionCount = 0,
|
||||||
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
||||||
|
MsgCountRoot = greatest(cm.MsgCountRoot, c.TotalMsgCountRoot),
|
||||||
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
||||||
LastUpdateAt = greatest(cm.LastViewedAt, c.LastPostAt)
|
LastUpdateAt = greatest(cm.LastViewedAt, c.LastPostAt)
|
||||||
FROM c
|
FROM c
|
||||||
@@ -2106,6 +2118,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
msgCountQuery := ""
|
msgCountQuery := ""
|
||||||
|
msgCountQueryRoot := ""
|
||||||
lastViewedQuery := ""
|
lastViewedQuery := ""
|
||||||
|
|
||||||
for index, t := range lastPostAtTimes {
|
for index, t := range lastPostAtTimes {
|
||||||
@@ -2114,6 +2127,9 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
|
props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
|
||||||
msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
|
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
|
props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
|
||||||
lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
|
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
|
SET
|
||||||
MentionCount = 0,
|
MentionCount = 0,
|
||||||
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
||||||
|
MsgCountRoot = CASE ChannelId ` + msgCountQueryRoot + ` END,
|
||||||
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
||||||
LastUpdateAt = LastViewedAt
|
LastUpdateAt = LastViewedAt
|
||||||
WHERE
|
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.
|
// 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) {
|
func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, userId string) (int, int, error) {
|
||||||
joinLeavePostTypes, params := MapStringsToQueryParams([]string{
|
joinLeavePostTypes := []string{
|
||||||
// These types correspond to the ones checked by Post.IsJoinLeaveMessage
|
// These types correspond to the ones checked by Post.IsJoinLeaveMessage
|
||||||
model.POST_JOIN_LEAVE,
|
model.POST_JOIN_LEAVE,
|
||||||
model.POST_ADD_REMOVE,
|
model.POST_ADD_REMOVE,
|
||||||
@@ -2155,31 +2172,25 @@ func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, user
|
|||||||
model.POST_REMOVE_FROM_CHANNEL,
|
model.POST_REMOVE_FROM_CHANNEL,
|
||||||
model.POST_ADD_TO_TEAM,
|
model.POST_ADD_TO_TEAM,
|
||||||
model.POST_REMOVE_FROM_TEAM,
|
model.POST_REMOVE_FROM_TEAM,
|
||||||
}, "PostType")
|
}
|
||||||
|
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})
|
||||||
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
|
|
||||||
|
|
||||||
if userId != "" {
|
if userId != "" {
|
||||||
query += " AND UserId = :UserId"
|
query = query.Where(sq.Eq{"UserId": userId})
|
||||||
params["UserId"] = userId
|
|
||||||
}
|
}
|
||||||
|
sql, args, _ := query.ToSql()
|
||||||
|
|
||||||
unread, err := s.GetReplica().SelectInt(query, params)
|
unread, err := s.GetReplica().SelectInt(sql, args...)
|
||||||
if err != nil {
|
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.
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"mentions": mentionCount,
|
"mentions": mentionCount,
|
||||||
"unreadCount": unread,
|
"unreadCount": unread,
|
||||||
"lastViewedAt": unreadDate,
|
"unreadCountRoot": unreadRoot,
|
||||||
"userId": userID,
|
"lastViewedAt": unreadDate,
|
||||||
"channelId": unreadPost.ChannelId,
|
"userId": userID,
|
||||||
"updatedAt": model.GetMillis(),
|
"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.
|
// 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
|
SET
|
||||||
MentionCount = :mentions,
|
MentionCount = :mentions,
|
||||||
MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
|
MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
|
||||||
|
MsgCountRoot = (SELECT TotalMsgCountRoot FROM Channels WHERE ID = :channelId) - :unreadCountRoot,
|
||||||
LastViewedAt = :lastViewedAt,
|
LastViewedAt = :lastViewedAt,
|
||||||
LastUpdateAt = :updatedAt
|
LastUpdateAt = :updatedAt
|
||||||
WHERE
|
WHERE
|
||||||
@@ -2235,6 +2248,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
|||||||
cm.UserId UserId,
|
cm.UserId UserId,
|
||||||
cm.ChannelId ChannelId,
|
cm.ChannelId ChannelId,
|
||||||
cm.MsgCount MsgCount,
|
cm.MsgCount MsgCount,
|
||||||
|
cm.MsgCountRoot MsgCountRoot,
|
||||||
cm.MentionCount MentionCount,
|
cm.MentionCount MentionCount,
|
||||||
cm.LastViewedAt LastViewedAt,
|
cm.LastViewedAt LastViewedAt,
|
||||||
cm.NotifyProps NotifyProps
|
cm.NotifyProps NotifyProps
|
||||||
|
|||||||
@@ -917,6 +917,7 @@ func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.Chan
|
|||||||
"ChannelMembers.UserId",
|
"ChannelMembers.UserId",
|
||||||
"ChannelMembers.LastViewedAt",
|
"ChannelMembers.LastViewedAt",
|
||||||
"ChannelMembers.MsgCount",
|
"ChannelMembers.MsgCount",
|
||||||
|
"ChannelMembers.MsgCountRoot",
|
||||||
"ChannelMembers.MentionCount",
|
"ChannelMembers.MentionCount",
|
||||||
"ChannelMembers.NotifyProps",
|
"ChannelMembers.NotifyProps",
|
||||||
"ChannelMembers.LastUpdateAt",
|
"ChannelMembers.LastUpdateAt",
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ func (s *SqlPostStore) createIndexesIfNotExists() {
|
|||||||
|
|
||||||
func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, error) {
|
func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, error) {
|
||||||
channelNewPosts := make(map[string]int)
|
channelNewPosts := make(map[string]int)
|
||||||
|
channelNewRootPosts := make(map[string]int)
|
||||||
maxDateNewPosts := make(map[string]int64)
|
maxDateNewPosts := make(map[string]int64)
|
||||||
rootIds := make(map[string]int)
|
rootIds := make(map[string]int)
|
||||||
maxDateRootIds := make(map[string]int64)
|
maxDateRootIds := make(map[string]int64)
|
||||||
@@ -125,8 +126,7 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
|||||||
return nil, idx, err
|
return nil, idx, err
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChannelCount, ok := channelNewPosts[post.ChannelId]
|
if currentChannelCount, ok := channelNewPosts[post.ChannelId]; !ok {
|
||||||
if !ok {
|
|
||||||
if post.IsJoinLeaveMessage() {
|
if post.IsJoinLeaveMessage() {
|
||||||
channelNewPosts[post.ChannelId] = 0
|
channelNewPosts[post.ChannelId] = 0
|
||||||
} else {
|
} else {
|
||||||
@@ -143,11 +143,21 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if post.RootId == "" {
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRootCount, ok := rootIds[post.RootId]
|
if currentRootCount, ok := rootIds[post.RootId]; !ok {
|
||||||
if !ok {
|
|
||||||
rootIds[post.RootId] = 1
|
rootIds[post.RootId] = 1
|
||||||
maxDateRootIds[post.RootId] = post.CreateAt
|
maxDateRootIds[post.RootId] = post.CreateAt
|
||||||
} else {
|
} else {
|
||||||
@@ -188,7 +198,9 @@ func (s *SqlPostStore) SaveMultiple(posts []*model.Post) ([]*model.Post, int, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
for channelId, count := range channelNewPosts {
|
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))
|
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.
|
// for all the channels in all the teams except the excluded ones.
|
||||||
func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) ([]*model.ChannelUnread, error) {
|
func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) ([]*model.ChannelUnread, error) {
|
||||||
query, args, err := s.getQueryBuilder().
|
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").
|
From("Channels").
|
||||||
Join("ChannelMembers ON Id = ChannelId").
|
Join("ChannelMembers ON Id = ChannelId").
|
||||||
Where(sq.Eq{"UserId": userId, "DeleteAt": 0}).
|
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.
|
// 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) {
|
func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) ([]*model.ChannelUnread, error) {
|
||||||
query, args, err := s.getQueryBuilder().
|
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").
|
From("Channels").
|
||||||
Join("ChannelMembers ON Id = ChannelId").
|
Join("ChannelMembers ON Id = ChannelId").
|
||||||
Where(sq.Eq{"UserId": userId, "TeamId": teamId, "DeleteAt": 0}).ToSql()
|
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.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)
|
// saveSchemaVersion(sqlStore, Version5350)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ package sqlstore
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
"github.com/mattermost/mattermost-server/v5/store"
|
"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
|
PermanentDeleteMembersByChannel(channelID string) error
|
||||||
UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, 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)
|
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
|
IncrementMentionCount(channelID string, userId string, updateThreads bool) error
|
||||||
AnalyticsTypeCount(teamID string, channelType string) (int64, error)
|
AnalyticsTypeCount(teamID string, channelType string) (int64, error)
|
||||||
GetMembersForUser(teamID string, userId string) (*model.ChannelMembers, error)
|
GetMembersForUser(teamID string, userId string) (*model.ChannelMembers, error)
|
||||||
|
|||||||
@@ -327,20 +327,20 @@ func testGetChannelUnread(t *testing.T, ss store.Store) {
|
|||||||
notifyPropsModel := model.GetDefaultChannelNotifyProps()
|
notifyPropsModel := model.GetDefaultChannelNotifyProps()
|
||||||
|
|
||||||
// Setup Channel 1
|
// 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)
|
_, nErr = ss.Channel().Save(c1, -1)
|
||||||
require.NoError(t, nErr)
|
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)
|
_, err := ss.Channel().SaveMember(cm1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Setup Channel 2
|
// 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)
|
_, nErr = ss.Channel().Save(c2, -1)
|
||||||
require.NoError(t, nErr)
|
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)
|
_, err = ss.Channel().SaveMember(cm2)
|
||||||
require.NoError(t, err)
|
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.NotNil(t, ch.NotifyProps, "wrong props for channel 1")
|
||||||
require.EqualValues(t, 0, ch.MentionCount, "wrong MentionCount 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, 10, ch.MsgCount, "wrong MsgCount for channel 1")
|
||||||
|
require.EqualValues(t, 19, ch.MsgCountRoot, "wrong MsgCountRoot for channel 1")
|
||||||
// Check for Channel 2
|
// Check for Channel 2
|
||||||
ch2, nErr := ss.Channel().GetChannelUnread(c2.Id, uid)
|
ch2, nErr := ss.Channel().GetChannelUnread(c2.Id, uid)
|
||||||
|
|
||||||
@@ -4007,19 +4007,19 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 3, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 2, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 2, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
})
|
})
|
||||||
@@ -4044,11 +4044,11 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 1, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
})
|
})
|
||||||
@@ -4105,19 +4105,19 @@ func testCountPostsAfter(t *testing.T, ss store.Store) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 3, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 2, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 2, count)
|
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)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
})
|
})
|
||||||
@@ -6345,9 +6345,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlStore) {
|
|||||||
|
|
||||||
_, execerr = s.GetMaster().ExecNoTimeout(`
|
_, execerr = s.GetMaster().ExecNoTimeout(`
|
||||||
INSERT INTO
|
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
|
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{}{
|
`, map[string]interface{}{
|
||||||
"Id": o3.Id,
|
"Id": o3.Id,
|
||||||
"CreateAt": o3.CreateAt,
|
"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
|
// 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)
|
ret := _m.Called(channelID, timestamp, userId)
|
||||||
|
|
||||||
var r0 int
|
var r0 int
|
||||||
@@ -150,14 +150,21 @@ func (_m *ChannelStore) CountPostsAfter(channelID string, timestamp int64, userI
|
|||||||
r0 = ret.Get(0).(int)
|
r0 = ret.Get(0).(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 int
|
||||||
if rf, ok := ret.Get(1).(func(string, int64, string) error); ok {
|
if rf, ok := ret.Get(1).(func(string, int64, string) int); ok {
|
||||||
r1 = rf(channelID, timestamp, userId)
|
r1 = rf(channelID, timestamp, userId)
|
||||||
} else {
|
} 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
|
// CreateDirectChannel provides a mock function with given fields: userId, otherUserId
|
||||||
|
|||||||
@@ -599,10 +599,10 @@ func (s *TimerLayerChannelStore) ClearSidebarOnTeamLeave(userId string, teamID s
|
|||||||
return err
|
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()
|
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)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
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)
|
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) {
|
func (s *TimerLayerChannelStore) CreateDirectChannel(userId *model.User, otherUserId *model.User) (*model.Channel, error) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user