We add the necessary store methods to use GraphQL

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2022-02-02 22:44:22 +05:30
коммит произвёл GitHub
родитель e9a777f4e2
Коммит a733fb840d
23 изменённых файлов: 1037 добавлений и 59 удалений

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

@@ -885,7 +885,10 @@ func getChannelsForTeamForUser(c *Context, w http.ResponseWriter, r *http.Reques
return return
} }
channels, err := c.App.GetChannelsForTeamForUser(c.Params.TeamId, c.Params.UserId, c.Params.IncludeDeleted, lastDeleteAt) channels, err := c.App.GetChannelsForTeamForUser(c.Params.TeamId, c.Params.UserId, &model.ChannelSearchOpts{
IncludeDeleted: c.Params.IncludeDeleted,
LastDeleteAt: lastDeleteAt,
})
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

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

@@ -210,7 +210,10 @@ func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.R
} }
func validateSidebarCategory(c *Context, teamId, userId string, category *model.SidebarCategoryWithChannels) *model.AppError { func validateSidebarCategory(c *Context, teamId, userId string, category *model.SidebarCategoryWithChannels) *model.AppError {
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, true, 0) channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
})
if err != nil { if err != nil {
return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest) return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest)
} }
@@ -221,7 +224,10 @@ func validateSidebarCategory(c *Context, teamId, userId string, category *model.
} }
func validateSidebarCategories(c *Context, teamId, userId string, categories []*model.SidebarCategoryWithChannels) *model.AppError { func validateSidebarCategories(c *Context, teamId, userId string, categories []*model.SidebarCategoryWithChannels) *model.AppError {
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, true, 0) channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
})
if err != nil { if err != nil {
return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest) return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest)
} }

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

@@ -573,7 +573,8 @@ type AppIface interface {
GetChannelsForRetentionPolicy(policyID string, offset, limit int) (*model.ChannelsWithCount, *model.AppError) GetChannelsForRetentionPolicy(policyID string, offset, limit int) (*model.ChannelsWithCount, *model.AppError)
GetChannelsForScheme(scheme *model.Scheme, offset int, limit int) (model.ChannelList, *model.AppError) GetChannelsForScheme(scheme *model.Scheme, offset int, limit int) (model.ChannelList, *model.AppError)
GetChannelsForSchemePage(scheme *model.Scheme, page int, perPage int) (model.ChannelList, *model.AppError) GetChannelsForSchemePage(scheme *model.Scheme, page int, perPage int) (model.ChannelList, *model.AppError)
GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError) GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError)
GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError)
GetChannelsForUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, *model.AppError) GetChannelsForUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, *model.AppError)
GetChannelsUserNotIn(teamID string, userID string, offset int, limit int) (model.ChannelList, *model.AppError) GetChannelsUserNotIn(teamID string, userID string, offset int, limit int) (model.ChannelList, *model.AppError)
GetCloudSession(token string) (*model.Session, *model.AppError) GetCloudSession(token string) (*model.Session, *model.AppError)

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

@@ -1767,8 +1767,23 @@ func (a *App) GetChannelByNameForTeamName(channelName, teamName string, includeD
return result, nil return result, nil
} }
func (a *App) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError) { func (a *App) GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError) {
list, err := a.Srv().Store.Channel().GetChannels(teamID, userID, includeDeleted, lastDeleteAt) list, err := a.Srv().Store.Channel().GetChannels(teamID, userID, opts)
if err != nil {
var nfErr *store.ErrNotFound
switch {
case errors.As(err, &nfErr):
return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound)
default:
return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
}
}
return list, nil
}
func (a *App) GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError) {
list, err := a.Srv().Store.Channel().GetChannelsWithCursor(teamID, userID, opts, afterChannelID)
if err != nil { if err != nil {
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {

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

@@ -997,19 +997,28 @@ func TestGetChannelsForUser(t *testing.T) {
defer th.App.PermanentDeleteChannel(channel) defer th.App.PermanentDeleteChannel(channel)
defer th.TearDown() defer th.TearDown()
channelList, err := th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, false, 0) channelList, err := th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelList, 4) require.Len(t, channelList, 4)
th.App.DeleteChannel(th.Context, channel, th.BasicUser.Id) th.App.DeleteChannel(th.Context, channel, th.BasicUser.Id)
// Now we get all the non-archived channels for the user // Now we get all the non-archived channels for the user
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, false, 0) channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelList, 3) require.Len(t, channelList, 3)
// Now we get all the channels, even though are archived, for the user // Now we get all the channels, even though are archived, for the user
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, true, 0) channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
})
require.Nil(t, err) require.Nil(t, err)
require.Len(t, channelList, 4) require.Len(t, channelList, 4)
} }

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

@@ -5203,7 +5203,7 @@ func (a *OpenTracingAppLayer) GetChannelsForSchemePage(scheme *model.Scheme, pag
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError) { func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelsForTeamForUser") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelsForTeamForUser")
@@ -5215,7 +5215,29 @@ func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID st
}() }()
defer span.Finish() defer span.Finish()
resultVar0, resultVar1 := a.app.GetChannelsForTeamForUser(teamID, userID, includeDeleted, lastDeleteAt) resultVar0, resultVar1 := a.app.GetChannelsForTeamForUser(teamID, userID, opts)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelsForTeamForUserWithCursor")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetChannelsForTeamForUserWithCursor(teamID, userID, opts, afterChannelID)
if resultVar1 != nil { if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1)) span.LogFields(spanlog.Error(resultVar1))

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

@@ -437,7 +437,10 @@ func (api *PluginAPI) GetChannelByNameForTeamName(teamName, channelName string,
} }
func (api *PluginAPI) GetChannelsForTeamForUser(teamID, userID string, includeDeleted bool) ([]*model.Channel, *model.AppError) { func (api *PluginAPI) GetChannelsForTeamForUser(teamID, userID string, includeDeleted bool) ([]*model.Channel, *model.AppError) {
channels, err := api.app.GetChannelsForTeamForUser(teamID, userID, includeDeleted, 0) channels, err := api.app.GetChannelsForTeamForUser(teamID, userID, &model.ChannelSearchOpts{
IncludeDeleted: includeDeleted,
LastDeleteAt: 0,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }

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

@@ -1116,7 +1116,10 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User,
var channelList model.ChannelList var channelList model.ChannelList
var nErr error var nErr error
if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, true, 0); nErr != nil { if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
}); nErr != nil {
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
if errors.As(nErr, &nfErr) { if errors.As(nErr, &nfErr) {
channelList = model.ChannelList{} channelList = model.ChannelList{}

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

@@ -868,7 +868,10 @@ func (a *App) invalidateUserChannelMembersCaches(userID string) *model.AppError
} }
for _, team := range teamsForUser { for _, team := range teamsForUser {
channelsForUser, err := a.GetChannelsForTeamForUser(team.Id, userID, false, 0) channelsForUser, err := a.GetChannelsForTeamForUser(team.Id, userID, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
if err != nil { if err != nil {
return err return err
} }

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

@@ -178,7 +178,10 @@ func manualTest(c *web.Context, w http.ResponseWriter, r *http.Request) {
func getChannelID(a app.AppIface, channelname string, teamid string, userid string) (string, bool) { func getChannelID(a app.AppIface, channelname string, teamid string, userid string) (string, bool) {
// Grab all the channels // Grab all the channels
channels, err := a.Srv().Store.Channel().GetChannels(teamid, userid, false, 0) channels, err := a.Srv().Store.Channel().GetChannels(teamid, userid, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
if err != nil { if err != nil {
mlog.Debug("Unable to get channels") mlog.Debug("Unable to get channels")
return "", false return "", false

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

@@ -141,6 +141,8 @@ type ChannelSearchOpts struct {
Private bool Private bool
Page *int Page *int
PerPage *int PerPage *int
LastDeleteAt int
LastUpdateAt int
} }
type ChannelMemberCountByGroup struct { type ChannelMemberCountByGroup struct {

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

@@ -1087,7 +1087,7 @@ func (s *OpenTracingLayerChannelStore) GetChannelUnread(channelID string, userID
return result, err return result, err
} }
func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) { func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
origCtx := s.Root.Store.Context() origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannels") span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannels")
s.Root.Store.SetContext(newCtx) s.Root.Store.SetContext(newCtx)
@@ -1096,7 +1096,7 @@ func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string,
}() }()
defer span.Finish() defer span.Finish()
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt) result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
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)
@@ -1177,6 +1177,24 @@ func (s *OpenTracingLayerChannelStore) GetChannelsByUser(userID string, includeD
return result, err return result, err
} }
func (s *OpenTracingLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsWithCursor")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) { func (s *OpenTracingLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
origCtx := s.Root.Store.Context() origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsWithTeamDataByIds") span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsWithTeamDataByIds")
@@ -1442,6 +1460,24 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUser(teamID string, userID s
return result, err return result, err
} }
func (s *OpenTracingLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersForUserWithCursor")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) { func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
origCtx := s.Root.Store.Context() origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersForUserWithPagination") span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersForUserWithPagination")
@@ -1460,6 +1496,24 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(userID st
return result, err return result, err
} }
func (s *OpenTracingLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersInfoByChannelIds")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) { func (s *OpenTracingLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
origCtx := s.Root.Store.Context() origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMoreChannels") span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMoreChannels")
@@ -2446,6 +2500,24 @@ func (s *OpenTracingLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int
return result, err return result, err
} }
func (s *OpenTracingLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelMemberHistoryStore.GetChannelsLeftSince")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) { func (s *OpenTracingLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
origCtx := s.Root.Store.Context() origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelMemberHistoryStore.GetUsersInChannelDuring") span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelMemberHistoryStore.GetUsersInChannelDuring")

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

@@ -1213,11 +1213,11 @@ func (s *RetryLayerChannelStore) GetChannelUnread(channelID string, userID strin
} }
func (s *RetryLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) { func (s *RetryLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
tries := 0 tries := 0
for { for {
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt) result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
if err == nil { if err == nil {
return result, nil return result, nil
} }
@@ -1318,6 +1318,27 @@ func (s *RetryLayerChannelStore) GetChannelsByUser(userID string, includeDeleted
} }
func (s *RetryLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
tries := 0
for {
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) { func (s *RetryLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
tries := 0 tries := 0
@@ -1618,6 +1639,27 @@ func (s *RetryLayerChannelStore) GetMembersForUser(teamID string, userID string)
} }
func (s *RetryLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
tries := 0
for {
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) { func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
tries := 0 tries := 0
@@ -1639,6 +1681,27 @@ func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string,
} }
func (s *RetryLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
tries := 0
for {
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) { func (s *RetryLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
tries := 0 tries := 0
@@ -2716,6 +2779,27 @@ func (s *RetryLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int
} }
func (s *RetryLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
tries := 0
for {
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
timepkg.Sleep(100 * timepkg.Millisecond)
}
}
func (s *RetryLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) { func (s *RetryLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
tries := 0 tries := 0

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

@@ -160,7 +160,10 @@ func (s SearchFileInfoStore) PermanentDeleteByUser(userId string) (int64, error)
func (s SearchFileInfoStore) Search(paramsList []*model.SearchParams, userId, teamId string, page, perPage int) (*model.FileInfoList, error) { func (s SearchFileInfoStore) Search(paramsList []*model.SearchParams, userId, teamId string, page, perPage int) (*model.FileInfoList, error) {
for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { for _, engine := range s.rootStore.searchEngine.GetActiveEngines() {
if engine.IsSearchEnabled() { if engine.IsSearchEnabled() {
userChannels, nErr := s.rootStore.Channel().GetChannels(teamId, userId, paramsList[0].IncludeDeletedChannels, 0) userChannels, nErr := s.rootStore.Channel().GetChannels(teamId, userId, &model.ChannelSearchOpts{
IncludeDeleted: paramsList[0].IncludeDeletedChannels,
LastDeleteAt: 0,
})
if nErr != nil { if nErr != nil {
return nil, nErr return nil, nErr
} }

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

@@ -142,7 +142,11 @@ func (s SearchPostStore) searchPostsForUserByEngine(engine searchengine.SearchEn
} }
// We only allow the user to search in channels they are a member of. // We only allow the user to search in channels they are a member of.
userChannels, err2 := s.rootStore.Channel().GetChannels(teamId, userId, paramsList[0].IncludeDeletedChannels, 0) userChannels, err2 := s.rootStore.Channel().GetChannels(teamId, userId,
&model.ChannelSearchOpts{
IncludeDeleted: paramsList[0].IncludeDeletedChannels,
LastDeleteAt: 0,
})
if err2 != nil { if err2 != nil {
return nil, errors.Wrap(err2, "error getting channel for user") return nil, errors.Wrap(err2, "error getting channel for user")
} }

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

@@ -255,3 +255,24 @@ func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit
} }
return rowsAffected, nil return rowsAffected, nil
} }
// GetChannelsLeftSince returns list of channels that the user has left after a given time,
// but has not rejoined again.
func (s SqlChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
query, params, err := s.getQueryBuilder().
Select("ChannelId").
From("ChannelMemberHistory").
GroupBy("ChannelId").
Where(sq.Eq{"UserId": userID}).
Having("MAX(LeaveTime) > MAX(JoinTime) AND MAX(LeaveTime) IS NOT NULL AND MAX(LeaveTime) >= ?", since).ToSql()
if err != nil {
return nil, errors.Wrap(err, "channel_member_history_to_sql")
}
channelIds := []string{}
err = s.GetReplicaX().Select(&channelIds, query, params...)
if err != nil {
return nil, errors.Wrapf(err, "GetChannelsLeftSince userId=%s since=%d", userID, since)
}
return channelIds, nil
}

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

@@ -1084,37 +1084,105 @@ func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) error
return nil return nil
} }
func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) { func (s SqlChannelStore) GetChannels(teamId string, userId string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
query := s.getQueryBuilder(). query := s.getQueryBuilder().
Select("Channels.*"). Select("ch.*").
From("Channels, ChannelMembers"). From("Channels ch, ChannelMembers cm").
Where( Where(
sq.And{ sq.And{
sq.Expr("Id = ChannelId"), sq.Expr("ch.Id = cm.ChannelId"),
sq.Eq{"UserId": userId}, sq.Eq{"cm.UserId": userId},
}, },
). ).
OrderBy("DisplayName") OrderBy("ch.DisplayName")
if teamId != "" { if teamId != "" {
query = query.Where(sq.Or{ query = query.Where(sq.Or{
sq.Eq{"TeamId": teamId}, sq.Eq{"ch.TeamId": teamId},
sq.Eq{"TeamId": ""}, sq.Eq{"ch.TeamId": ""},
}) })
} }
if includeDeleted { if opts.IncludeDeleted {
if lastDeleteAt != 0 { if opts.LastDeleteAt != 0 {
// We filter by non-archived, and archived >= a timestamp. // We filter by non-archived, and archived >= a timestamp.
query = query.Where(sq.Or{ query = query.Where(sq.Or{
sq.Eq{"DeleteAt": 0}, sq.Eq{"ch.DeleteAt": 0},
sq.GtOrEq{"DeleteAt": lastDeleteAt}, sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
}) })
} }
// If lastDeleteAt is not set, we include everything. That means no filter is needed. // If opts.LastDeleteAt is not set, we include everything. That means no filter is needed.
} else { } else {
// Don't include archived channels. // Don't include archived channels.
query = query.Where(sq.Eq{"DeleteAt": 0}) query = query.Where(sq.Eq{"ch.DeleteAt": 0})
}
if opts.LastUpdateAt > 0 {
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
}
channels := model.ChannelList{}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrapf(err, "getchannels_tosql")
}
err = s.GetReplicaX().Select(&channels, sql, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to get channels with TeamId=%s and UserId=%s", teamId, userId)
}
if len(channels) == 0 {
return nil, store.NewErrNotFound("Channel", "userId="+userId)
}
return channels, nil
}
func (s SqlChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
query := s.getQueryBuilder().
Select("ch.*").
From("Channels ch, ChannelMembers cm").
Where(
sq.And{
sq.Expr("ch.Id = cm.ChannelId"),
sq.Eq{"cm.UserId": userId},
},
).
OrderBy("ch.Id")
if opts.PerPage != nil {
// The limit is verified at the GraphQL layer.
query = query.Limit(uint64(*opts.PerPage))
}
if afterChannelID != "" {
query = query.Where(sq.Gt{"ch.Id": afterChannelID})
}
if teamId != "" {
query = query.Where(sq.Or{
sq.Eq{"ch.TeamId": teamId},
sq.Eq{"ch.TeamId": ""},
})
}
if opts.IncludeDeleted {
if opts.LastDeleteAt != 0 {
// We filter by non-archived, and archived >= a timestamp.
query = query.Where(sq.Or{
sq.Eq{"ch.DeleteAt": 0},
sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
})
}
// If opts.LastDeleteAt is not set, we include everything. That means no filter is needed.
} else {
// Don't include archived channels.
query = query.Where(sq.Eq{"ch.DeleteAt": 0})
}
if opts.LastUpdateAt > 0 {
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
} }
channels := model.ChannelList{} channels := model.ChannelList{}
@@ -2773,6 +2841,56 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (model.
return dbMembers.ToModel(), nil return dbMembers.ToModel(), nil
} }
func (s SqlChannelStore) GetMembersForUserWithCursor(userID, afterChannel, afterUser string, limit, lastUpdateAt int) (model.ChannelMembers, error) {
query := s.getQueryBuilder().
Select("ChannelMembers.*",
"TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole",
"TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole",
"TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole",
"ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole",
"ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole",
"ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole").
From("ChannelMembers").
InnerJoin("Channels ON ChannelMembers.ChannelId = Channels.Id").
LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
LeftJoin("Teams ON Channels.TeamId = Teams.Id").
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
Where(sq.Eq{
"ChannelMembers.UserId": userID,
"Channels.DeleteAt": 0,
}).
OrderBy("ChannelId, UserId ASC").
// The limit is verified at the GraphQL layer.
Limit(uint64(limit))
if afterChannel != "" && afterUser != "" {
query = query.Where(sq.Or{
sq.Gt{"ChannelMembers.ChannelId": afterChannel},
sq.And{
sq.Eq{"ChannelMembers.ChannelId": afterChannel},
sq.Gt{"ChannelMembers.UserId": afterUser},
},
})
}
if lastUpdateAt != 0 {
query = query.Where(sq.GtOrEq{"ChannelMembers.LastUpdateAt": lastUpdateAt})
}
queryString, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "getMembersForUserWithCursor_tosql")
}
dbMembers := channelMemberWithSchemeRolesList{}
err = s.GetReplicaX().Select(&dbMembers, queryString, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s", userID)
}
return dbMembers.ToModel(), nil
}
func (s SqlChannelStore) GetMembersForUserWithPagination(userId string, page, perPage int) (model.ChannelMembersWithTeamData, error) { func (s SqlChannelStore) GetMembersForUserWithPagination(userId string, page, perPage int) (model.ChannelMembersWithTeamData, error) {
dbMembers := channelMemberWithTeamWithSchemeRolesList{} dbMembers := channelMemberWithTeamWithSchemeRolesList{}
offset := page * perPage offset := page * perPage
@@ -3470,6 +3588,43 @@ func (s SqlChannelStore) GetMembersByChannelIds(channelIds []string, userId stri
return dbMembers.ToModel(), nil return dbMembers.ToModel(), nil
} }
func (s SqlChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
query := s.getQueryBuilder().
Select("Channels.Id as ChannelId, Users.Id, Users.FirstName, Users.LastName, Users.Nickname, Users.Username").
From("ChannelMembers as cm").
Join("Channels ON cm.ChannelId = Channels.Id").
Join("Users ON cm.UserId = Users.Id").
Where(sq.Eq{
"Channels.Id": channelIDs,
"Channels.DeleteAt": 0,
})
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "dm_gm_names_tosql")
}
res := []*struct {
model.User
ChannelId string
}{}
if err := s.GetReplicaX().Select(&res, sql, args...); err != nil {
return nil, errors.Wrap(err, "failed to find channels display name")
}
if len(res) == 0 {
return nil, store.NewErrNotFound("User", fmt.Sprintf("%v", channelIDs))
}
userInfo := make(map[string][]*model.User)
for _, item := range res {
userInfo[item.ChannelId] = append(userInfo[item.ChannelId], &item.User)
}
return userInfo, nil
}
func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) (model.ChannelList, error) { func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) (model.ChannelList, error) {
channels := model.ChannelList{} channels := model.ChannelList{}
err := s.GetReplicaX().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = ? ORDER BY DisplayName LIMIT ? OFFSET ?", schemeId, limit, offset) err := s.GetReplicaX().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = ? ORDER BY DisplayName LIMIT ? OFFSET ?", schemeId, limit, offset)

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

@@ -178,7 +178,8 @@ type ChannelStore interface {
GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*model.Channel, error) GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*model.Channel, error)
GetDeletedByName(team_id string, name string) (*model.Channel, error) GetDeletedByName(team_id string, name string) (*model.Channel, error)
GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error) GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error)
GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) GetChannels(teamID, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error)
GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error)
GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, error) GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, error)
GetAllChannelMembersById(id string) ([]string, error) GetAllChannelMembersById(id string) ([]string, error)
GetAllChannels(page, perPage int, opts ChannelSearchOpts) (model.ChannelListWithTeamData, error) GetAllChannels(page, perPage int, opts ChannelSearchOpts) (model.ChannelListWithTeamData, error)
@@ -230,6 +231,7 @@ type ChannelStore interface {
GetMembersForUser(teamID string, userID string) (model.ChannelMembers, error) GetMembersForUser(teamID string, userID string) (model.ChannelMembers, error)
GetTeamMembersForChannel(channelID string) ([]string, error) GetTeamMembersForChannel(channelID string) ([]string, error)
GetMembersForUserWithPagination(userID string, page, perPage int) (model.ChannelMembersWithTeamData, error) GetMembersForUserWithPagination(userID string, page, perPage int) (model.ChannelMembersWithTeamData, error)
GetMembersForUserWithCursor(userID, afterChannel, afterUser string, limit, lastUpdateAt int) (model.ChannelMembers, error)
Autocomplete(userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) Autocomplete(userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error)
AutocompleteInTeam(teamID, userID, term string, includeDeleted bool) (model.ChannelList, error) AutocompleteInTeam(teamID, userID, term string, includeDeleted bool) (model.ChannelList, error)
AutocompleteInTeamForSearch(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error) AutocompleteInTeamForSearch(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error)
@@ -241,6 +243,7 @@ type ChannelStore interface {
SearchGroupChannels(userID, term string) (model.ChannelList, error) SearchGroupChannels(userID, term string) (model.ChannelList, error)
GetMembersByIds(channelID string, userIds []string) (model.ChannelMembers, error) GetMembersByIds(channelID string, userIds []string) (model.ChannelMembers, error)
GetMembersByChannelIds(channelIds []string, userID string) (model.ChannelMembers, error) GetMembersByChannelIds(channelIds []string, userID string) (model.ChannelMembers, error)
GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error)
AnalyticsDeletedTypeCount(teamID string, channelType string) (int64, error) AnalyticsDeletedTypeCount(teamID string, channelType string) (int64, error)
GetChannelUnread(channelID, userID string) (*model.ChannelUnread, error) GetChannelUnread(channelID, userID string) (*model.ChannelUnread, error)
ClearCaches() ClearCaches()
@@ -284,6 +287,7 @@ type ChannelMemberHistoryStore interface {
PermanentDeleteBatchForRetentionPolicies(now, globalPolicyEndTime, limit int64, cursor model.RetentionPolicyCursor) (int64, model.RetentionPolicyCursor, error) PermanentDeleteBatchForRetentionPolicies(now, globalPolicyEndTime, limit int64, cursor model.RetentionPolicyCursor) (int64, model.RetentionPolicyCursor, error)
DeleteOrphanedRows(limit int) (deleted int64, err error) DeleteOrphanedRows(limit int) (deleted int64, err error)
PermanentDeleteBatch(endTime int64, limit int64) (int64, error) PermanentDeleteBatch(endTime int64, limit int64) (int64, error)
GetChannelsLeftSince(userID string, since int64) ([]string, error)
} }
type ThreadStore interface { type ThreadStore interface {
GetThreadFollowers(threadID string, fetchOnlyActive bool) ([]string, error) GetThreadFollowers(threadID string, fetchOnlyActive bool) ([]string, error)
@@ -919,6 +923,8 @@ type ChannelSearchOpts struct {
Private bool Private bool
Page *int Page *int
PerPage *int PerPage *int
LastDeleteAt int
LastUpdateAt int
} }
func (c *ChannelSearchOpts) IsPaginated() bool { func (c *ChannelSearchOpts) IsPaginated() bool {

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

@@ -22,6 +22,7 @@ func TestChannelMemberHistoryStore(t *testing.T, ss store.Store) {
t.Run("TestGetUsersInChannelAtChannelMembers", func(t *testing.T) { testGetUsersInChannelAtChannelMembers(t, ss) }) t.Run("TestGetUsersInChannelAtChannelMembers", func(t *testing.T) { testGetUsersInChannelAtChannelMembers(t, ss) })
t.Run("TestPermanentDeleteBatch", func(t *testing.T) { testPermanentDeleteBatch(t, ss) }) t.Run("TestPermanentDeleteBatch", func(t *testing.T) { testPermanentDeleteBatch(t, ss) })
t.Run("TestPermanentDeleteBatchForRetentionPolicies", func(t *testing.T) { testPermanentDeleteBatchForRetentionPolicies(t, ss) }) t.Run("TestPermanentDeleteBatchForRetentionPolicies", func(t *testing.T) { testPermanentDeleteBatchForRetentionPolicies(t, ss) })
t.Run("TestGetChannelsLeftSince", func(t *testing.T) { testGetChannelsLeftSince(t, ss) })
} }
func testLogJoinEvent(t *testing.T, ss store.Store) { func testLogJoinEvent(t *testing.T, ss store.Store) {
@@ -29,7 +30,7 @@ func testLogJoinEvent(t *testing.T, ss store.Store) {
ch := model.Channel{ ch := model.Channel{
TeamId: model.NewId(), TeamId: model.NewId(),
DisplayName: "Display " + model.NewId(), DisplayName: "Display " + model.NewId(),
Name: "zz" + model.NewId() + "b", Name: NewTestId(),
Type: model.ChannelTypeOpen, Type: model.ChannelTypeOpen,
} }
channel, err := ss.Channel().Save(&ch, -1) channel, err := ss.Channel().Save(&ch, -1)
@@ -55,7 +56,7 @@ func testLogLeaveEvent(t *testing.T, ss store.Store) {
ch := model.Channel{ ch := model.Channel{
TeamId: model.NewId(), TeamId: model.NewId(),
DisplayName: "Display " + model.NewId(), DisplayName: "Display " + model.NewId(),
Name: "zz" + model.NewId() + "b", Name: NewTestId(),
Type: model.ChannelTypeOpen, Type: model.ChannelTypeOpen,
} }
channel, err := ss.Channel().Save(&ch, -1) channel, err := ss.Channel().Save(&ch, -1)
@@ -84,7 +85,7 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
ch := &model.Channel{ ch := &model.Channel{
TeamId: model.NewId(), TeamId: model.NewId(),
DisplayName: "Display " + model.NewId(), DisplayName: "Display " + model.NewId(),
Name: "zz" + model.NewId() + "b", Name: NewTestId(),
Type: model.ChannelTypeOpen, Type: model.ChannelTypeOpen,
} }
channel, err := ss.Channel().Save(ch, -1) channel, err := ss.Channel().Save(ch, -1)
@@ -180,7 +181,7 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
channel := &model.Channel{ channel := &model.Channel{
TeamId: model.NewId(), TeamId: model.NewId(),
DisplayName: "Display " + model.NewId(), DisplayName: "Display " + model.NewId(),
Name: "zz" + model.NewId() + "b", Name: NewTestId(),
Type: model.ChannelTypeOpen, Type: model.ChannelTypeOpen,
} }
channel, err := ss.Channel().Save(channel, -1) channel, err := ss.Channel().Save(channel, -1)
@@ -292,7 +293,7 @@ func testPermanentDeleteBatch(t *testing.T, ss store.Store) {
channel := &model.Channel{ channel := &model.Channel{
TeamId: model.NewId(), TeamId: model.NewId(),
DisplayName: "Display " + model.NewId(), DisplayName: "Display " + model.NewId(),
Name: "zz" + model.NewId() + "b", Name: NewTestId(),
Type: model.ChannelTypeOpen, Type: model.ChannelTypeOpen,
} }
channel, err := ss.Channel().Save(channel, -1) channel, err := ss.Channel().Save(channel, -1)
@@ -389,3 +390,54 @@ func testPermanentDeleteBatchForRetentionPolicies(t *testing.T, ss store.Store)
require.NoError(t, err) require.NoError(t, err)
require.Empty(t, result, "history should have been deleted by channel policy") require.Empty(t, result, "history should have been deleted by channel policy")
} }
func testGetChannelsLeftSince(t *testing.T, ss store.Store) {
team, err := ss.Team().Save(&model.Team{
DisplayName: "DisplayName",
Name: "team" + model.NewId(),
Email: MakeEmail(),
Type: model.TeamOpen,
})
require.NoError(t, err)
channel, err := ss.Channel().Save(&model.Channel{
TeamId: team.Id,
DisplayName: "DisplayName",
Name: "channel" + model.NewId(),
Type: model.ChannelTypeOpen,
}, -1)
require.NoError(t, err)
userID := model.NewId()
joinTime := int64(1000)
err = ss.ChannelMemberHistory().LogJoinEvent(userID, channel.Id, joinTime)
require.NoError(t, err)
// has not left
ids, err := ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime)
require.NoError(t, err)
assert.Empty(t, ids)
// left
err = ss.ChannelMemberHistory().LogLeaveEvent(userID, channel.Id, joinTime+100)
require.NoError(t, err)
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+100)
require.NoError(t, err)
assert.Equal(t, []string{channel.Id}, ids)
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+200)
require.NoError(t, err)
assert.Empty(t, ids)
// joined and left again.
err = ss.ChannelMemberHistory().LogJoinEvent(userID, channel.Id, joinTime+200)
require.NoError(t, err)
err = ss.ChannelMemberHistory().LogLeaveEvent(userID, channel.Id, joinTime+300)
require.NoError(t, err)
// should be same for both time stamps
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+100)
require.NoError(t, err)
assert.Equal(t, []string{channel.Id}, ids)
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+300)
require.NoError(t, err)
assert.Equal(t, []string{channel.Id}, ids)
}

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

@@ -79,6 +79,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("RemoveMembers", func(t *testing.T) { testChannelRemoveMembers(t, ss) }) t.Run("RemoveMembers", func(t *testing.T) { testChannelRemoveMembers(t, ss) })
t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) }) t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) })
t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) }) t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) })
t.Run("GetChannelsWithCursor", func(t *testing.T) { testChannelStoreGetChannelsWithCursor(t, ss) })
t.Run("GetChannelsByUser", func(t *testing.T) { testChannelStoreGetChannelsByUser(t, ss) }) t.Run("GetChannelsByUser", func(t *testing.T) { testChannelStoreGetChannelsByUser(t, ss) })
t.Run("GetAllChannels", func(t *testing.T) { testChannelStoreGetAllChannels(t, ss, s) }) t.Run("GetAllChannels", func(t *testing.T) { testChannelStoreGetAllChannels(t, ss, s) })
t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) }) t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) })
@@ -87,6 +88,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) }) t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) })
t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) }) t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) })
t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) }) t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) })
t.Run("GetMembersForUserWithCursor", func(t *testing.T) { testChannelStoreGetMembersForUserWithCursor(t, ss) })
t.Run("GetMembersForUserWithPagination", func(t *testing.T) { testChannelStoreGetMembersForUserWithPagination(t, ss) }) t.Run("GetMembersForUserWithPagination", func(t *testing.T) { testChannelStoreGetMembersForUserWithPagination(t, ss) })
t.Run("CountPostsAfter", func(t *testing.T) { testCountPostsAfter(t, ss) }) t.Run("CountPostsAfter", func(t *testing.T) { testCountPostsAfter(t, ss) })
t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) }) t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) })
@@ -105,6 +107,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("SearchAllChannels", func(t *testing.T) { testChannelStoreSearchAllChannels(t, ss) }) t.Run("SearchAllChannels", func(t *testing.T) { testChannelStoreSearchAllChannels(t, ss) })
t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) }) t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) })
t.Run("GetMembersByChannelIds", func(t *testing.T) { testChannelStoreGetMembersByChannelIds(t, ss) }) t.Run("GetMembersByChannelIds", func(t *testing.T) { testChannelStoreGetMembersByChannelIds(t, ss) })
t.Run("GetMembersInfoByChannelIds", func(t *testing.T) { testChannelStoreGetMembersInfoByChannelIds(t, ss) })
t.Run("SearchGroupChannels", func(t *testing.T) { testChannelStoreSearchGroupChannels(t, ss) }) t.Run("SearchGroupChannels", func(t *testing.T) { testChannelStoreSearchGroupChannels(t, ss) })
t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) }) t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) })
t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) }) t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) })
@@ -719,7 +722,10 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) {
nErr = ss.Channel().Delete(o3.Id, model.GetMillis()) nErr = ss.Channel().Delete(o3.Id, model.GetMillis())
require.NoError(t, nErr, nErr) require.NoError(t, nErr, nErr)
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0) list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 1, "invalid number of channels") require.Len(t, list, 1, "invalid number of channels")
@@ -730,7 +736,10 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) {
cresult := ss.Channel().PermanentDelete(o2.Id) cresult := ss.Channel().PermanentDelete(o2.Id)
require.NoError(t, cresult) require.NoError(t, cresult)
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0) list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
if assert.Error(t, nErr) { if assert.Error(t, nErr) {
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
require.True(t, errors.As(nErr, &nfErr)) require.True(t, errors.As(nErr, &nfErr))
@@ -3263,12 +3272,13 @@ func testChannelDeleteMemberStore(t *testing.T, ss store.Store) {
func testChannelStoreGetChannels(t *testing.T, ss store.Store) { func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
team := model.NewId() team := model.NewId()
o1 := model.Channel{} o1 := &model.Channel{}
o1.TeamId = team o1.TeamId = team
o1.DisplayName = "Channel1" o1.DisplayName = "Channel1"
o1.Name = NewTestId() o1.Name = NewTestId()
o1.Type = model.ChannelTypeOpen o1.Type = model.ChannelTypeOpen
_, nErr := ss.Channel().Save(&o1, -1) var nErr error
o1, nErr = ss.Channel().Save(o1, -1)
require.NoError(t, nErr) require.NoError(t, nErr)
o2 := model.Channel{} o2 := model.Channel{}
@@ -3315,7 +3325,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
_, err = ss.Channel().SaveMember(&m4) _, err = ss.Channel().SaveMember(&m4)
require.NoError(t, err) require.NoError(t, err)
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0) list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 3) require.Len(t, list, 3)
require.Equal(t, o1.Id, list[0].Id, "missing channel") require.Equal(t, o1.Id, list[0].Id, "missing channel")
@@ -3342,6 +3355,25 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
_, ok = ids4[o1.Id] _, ok = ids4[o1.Id]
require.True(t, ok, "missing channel") require.True(t, ok, "missing channel")
// Sleeping to guarantee that the
// UpdateAt is different.
// The proper way would be to set UpdateAt during channel creation itself,
// but the *Channel.PreSave method ignores any existing CreateAt value.
// TODO: check if using an existing CreateAt breaks anything.
time.Sleep(time.Millisecond)
now := model.GetMillis()
_, nErr = ss.Channel().Update(o1)
require.NoError(t, nErr)
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastUpdateAt: int(now),
})
require.NoError(t, nErr)
// should return 1
require.Len(t, list, 1)
nErr = ss.Channel().Delete(o2.Id, 10) nErr = ss.Channel().Delete(o2.Id, 10)
require.NoError(t, nErr) require.NoError(t, nErr)
@@ -3349,13 +3381,19 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
require.NoError(t, nErr) require.NoError(t, nErr)
// should return 1 // should return 1
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0) list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 1) require.Len(t, list, 1)
require.Equal(t, o1.Id, list[0].Id, "missing channel") require.Equal(t, o1.Id, list[0].Id, "missing channel")
// Should return all // Should return all
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, true, 0) list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 3) require.Len(t, list, 3)
require.Equal(t, o1.Id, list[0].Id, "missing channel") require.Equal(t, o1.Id, list[0].Id, "missing channel")
@@ -3363,7 +3401,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
require.Equal(t, o3.Id, list[2].Id, "missing channel") require.Equal(t, o3.Id, list[2].Id, "missing channel")
// Should still return all // Should still return all
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, true, 10) list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 10,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 3) require.Len(t, list, 3)
require.Equal(t, o1.Id, list[0].Id, "missing channel") require.Equal(t, o1.Id, list[0].Id, "missing channel")
@@ -3371,7 +3412,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
require.Equal(t, o3.Id, list[2].Id, "missing channel") require.Equal(t, o3.Id, list[2].Id, "missing channel")
// Should return 2 // Should return 2
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, true, 20) list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 20,
})
require.NoError(t, nErr) require.NoError(t, nErr)
require.Len(t, list, 2) require.Len(t, list, 2)
require.Equal(t, o1.Id, list[0].Id, "missing channel") require.Equal(t, o1.Id, list[0].Id, "missing channel")
@@ -3399,6 +3443,147 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId) ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId)
} }
func testChannelStoreGetChannelsWithCursor(t *testing.T, ss store.Store) {
teamID := model.NewId()
o1 := &model.Channel{}
o1.TeamId = teamID
o1.DisplayName = "Channel1"
o1.Name = NewTestId()
o1.Type = model.ChannelTypeOpen
var nErr error
o1, nErr = ss.Channel().Save(o1, -1)
require.NoError(t, nErr)
o2 := model.Channel{}
o2.TeamId = teamID
o2.DisplayName = "Channel2"
o2.Name = NewTestId()
o2.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o2, -1)
require.NoError(t, nErr)
o3 := model.Channel{}
o3.TeamId = teamID
o3.DisplayName = "Channel3"
o3.Name = NewTestId()
o3.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o3, -1)
require.NoError(t, nErr)
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err := ss.Channel().SaveMember(&m1)
require.NoError(t, err)
m2 := model.ChannelMember{}
m2.ChannelId = o1.Id
m2.UserId = model.NewId()
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m2)
require.NoError(t, err)
m3 := model.ChannelMember{}
m3.ChannelId = o2.Id
m3.UserId = m1.UserId
m3.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m3)
require.NoError(t, err)
m4 := model.ChannelMember{}
m4.ChannelId = o3.Id
m4.UserId = m1.UserId
m4.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m4)
require.NoError(t, err)
list, nErr := ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
PerPage: model.NewInt(2),
}, "")
require.NoError(t, nErr)
require.Len(t, list, 2)
require.Equal(t, teamID, list[0].TeamId, "incorrect teamID")
require.Equal(t, teamID, list[1].TeamId, "incorrect teamID")
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
PerPage: model.NewInt(2),
}, list[1].Id)
require.NoError(t, nErr)
require.Len(t, list, 1)
require.Equal(t, teamID, list[0].TeamId, "incorrect teamID")
// Sleeping to guarantee that the
// UpdateAt is different.
// The proper way would be to set UpdateAt during channel creation itself,
// but the *Channel.PreSave method ignores any existing CreateAt value.
// TODO: check if using an existing CreateAt breaks anything.
time.Sleep(time.Millisecond)
now := model.GetMillis()
_, nErr = ss.Channel().Update(o1)
require.NoError(t, nErr)
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastUpdateAt: int(now),
}, "")
require.NoError(t, nErr)
// should return 1
require.Len(t, list, 1)
nErr = ss.Channel().Delete(o2.Id, 10)
require.NoError(t, nErr)
nErr = ss.Channel().Delete(o3.Id, 20)
require.NoError(t, nErr)
// should return 1
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: false,
LastDeleteAt: 0,
}, "")
require.NoError(t, nErr)
require.Len(t, list, 1)
// Should return all
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
PerPage: model.NewInt(2),
}, "")
require.NoError(t, nErr)
require.Len(t, list, 2)
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 0,
PerPage: model.NewInt(2),
}, list[1].Id)
require.NoError(t, nErr)
require.Len(t, list, 1)
// Should still return all
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 10,
}, "")
require.NoError(t, nErr)
require.Len(t, list, 3)
// Should return 2
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
IncludeDeleted: true,
LastDeleteAt: 20,
}, "")
require.NoError(t, nErr)
require.Len(t, list, 2)
}
func testChannelStoreGetChannelsByUser(t *testing.T, ss store.Store) { func testChannelStoreGetChannelsByUser(t *testing.T, ss store.Store) {
team := model.NewId() team := model.NewId()
team2 := model.NewId() team2 := model.NewId()
@@ -4191,6 +4376,120 @@ func testChannelStoreGetMembersForUser(t *testing.T, ss store.Store) {
}) })
} }
func testChannelStoreGetMembersForUserWithCursor(t *testing.T, ss store.Store) {
t1 := model.Team{}
t1.DisplayName = "Team1"
t1.Name = NewTestId()
t1.Email = MakeEmail()
t1.Type = model.TeamOpen
_, err := ss.Team().Save(&t1)
require.NoError(t, err)
o1 := model.Channel{}
o1.TeamId = t1.Id
o1.DisplayName = "Channel1"
o1.Name = NewTestId()
o1.Type = model.ChannelTypeOpen
_, nErr := ss.Channel().Save(&o1, -1)
require.NoError(t, nErr)
o2 := model.Channel{}
o2.TeamId = o1.TeamId
o2.DisplayName = "Channel2"
o2.Name = NewTestId()
o2.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o2, -1)
require.NoError(t, nErr)
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m1)
require.NoError(t, err)
m2 := model.ChannelMember{}
m2.ChannelId = o2.Id
m2.UserId = m1.UserId
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m2)
require.NoError(t, err)
t.Run("with channels", func(t *testing.T) {
var members model.ChannelMembers
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 1, 0)
require.NoError(t, err)
assert.Len(t, members, 1)
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 3, 0)
require.NoError(t, err)
assert.Len(t, members, 2)
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[0].ChannelId, m1.UserId, 1, 0)
require.NoError(t, err)
assert.Len(t, members, 1)
})
t.Run("with channels and direct messages", func(t *testing.T) {
user := model.User{Id: m1.UserId}
u1 := model.User{Id: model.NewId()}
u2 := model.User{Id: model.NewId()}
u3 := model.User{Id: model.NewId()}
u4 := model.User{Id: model.NewId()}
_, nErr = ss.Channel().CreateDirectChannel(&u1, &user)
require.NoError(t, nErr)
_, nErr = ss.Channel().CreateDirectChannel(&u2, &user)
require.NoError(t, nErr)
// other user direct message
_, nErr = ss.Channel().CreateDirectChannel(&u3, &u4)
require.NoError(t, nErr)
members, err2 := ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 10, 0)
require.NoError(t, err2)
assert.Len(t, members, 4)
members, err2 = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 2, 0)
require.NoError(t, err2)
assert.Len(t, members, 2)
members, err2 = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[1].ChannelId, m1.UserId, 2, 0)
require.NoError(t, err2)
assert.Len(t, members, 2)
})
t.Run("with channels, direct channels and group messages", func(t *testing.T) {
userIds := []string{model.NewId(), model.NewId(), model.NewId(), m1.UserId}
group := &model.Channel{
Name: model.GetGroupNameFromUserIds(userIds),
DisplayName: "test",
Type: model.ChannelTypeGroup,
}
var channel *model.Channel
channel, nErr = ss.Channel().Save(group, 10000)
require.NoError(t, nErr)
for _, userId := range userIds {
cm := &model.ChannelMember{
UserId: userId,
ChannelId: channel.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
SchemeUser: true,
}
_, err = ss.Channel().SaveMember(cm)
require.NoError(t, err)
}
members, err := ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 10, 0)
require.NoError(t, err)
assert.Len(t, members, 5)
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 2, 0)
require.NoError(t, err)
assert.Len(t, members, 2)
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[1].ChannelId, m1.UserId, 10, 0)
require.NoError(t, err)
assert.Len(t, members, 3)
})
}
func testChannelStoreGetMembersForUserWithPagination(t *testing.T, ss store.Store) { func testChannelStoreGetMembersForUserWithPagination(t *testing.T, ss store.Store) {
t1 := model.Team{ t1 := model.Team{
DisplayName: "team1", DisplayName: "team1",
@@ -6072,6 +6371,62 @@ func testChannelStoreGetMembersByChannelIds(t *testing.T, ss store.Store) {
}) })
} }
func testChannelStoreGetMembersInfoByChannelIds(t *testing.T, ss store.Store) {
u, err := ss.User().Save(&model.User{
Username: "user.test",
Email: MakeEmail(),
Nickname: model.NewId(),
})
require.NoError(t, err)
// Create a couple channels and add the user to them
channel1, err := ss.Channel().Save(&model.Channel{
TeamId: model.NewId(),
DisplayName: model.NewId(),
Name: model.NewId(),
Type: model.ChannelTypeOpen,
}, -1)
require.NoError(t, err)
channel2, err := ss.Channel().Save(&model.Channel{
TeamId: model.NewId(),
DisplayName: model.NewId(),
Name: model.NewId(),
Type: model.ChannelTypeOpen,
}, -1)
require.NoError(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: channel1.Id,
UserId: u.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.NoError(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: channel2.Id,
UserId: u.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.NoError(t, err)
t.Run("should return the user's members for the given channels", func(t *testing.T) {
result, nErr := ss.Channel().GetMembersInfoByChannelIds([]string{channel1.Id, channel2.Id})
require.NoError(t, nErr)
assert.Len(t, result, 2)
for _, item := range result {
assert.Len(t, item, 1)
assert.Equal(t, u.Id, item[0].Id)
}
})
t.Run("should not error or return anything for invalid channel IDs", func(t *testing.T) {
_, err := ss.Channel().GetMembersInfoByChannelIds([]string{model.NewId(), model.NewId()})
var nfErr *store.ErrNotFound
require.True(t, errors.As(err, &nfErr))
})
}
func testChannelStoreSearchGroupChannels(t *testing.T, ss store.Store) { func testChannelStoreSearchGroupChannels(t *testing.T, ss store.Store) {
// Users // Users
u1 := &model.User{} u1 := &model.User{}

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

@@ -35,6 +35,29 @@ func (_m *ChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int64, error
return r0, r1 return r0, r1
} }
// GetChannelsLeftSince provides a mock function with given fields: userID, since
func (_m *ChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
ret := _m.Called(userID, since)
var r0 []string
if rf, ok := ret.Get(0).(func(string, int64) []string); ok {
r0 = rf(userID, since)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, int64) error); ok {
r1 = rf(userID, since)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetUsersInChannelDuring provides a mock function with given fields: startTime, endTime, channelID // GetUsersInChannelDuring provides a mock function with given fields: startTime, endTime, channelID
func (_m *ChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) { func (_m *ChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
ret := _m.Called(startTime, endTime, channelID) ret := _m.Called(startTime, endTime, channelID)

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

@@ -674,13 +674,13 @@ func (_m *ChannelStore) GetChannelUnread(channelID string, userID string) (*mode
return r0, r1 return r0, r1
} }
// GetChannels provides a mock function with given fields: teamID, userID, includeDeleted, lastDeleteAt // GetChannels provides a mock function with given fields: teamID, userID, opts
func (_m *ChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) { func (_m *ChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
ret := _m.Called(teamID, userID, includeDeleted, lastDeleteAt) ret := _m.Called(teamID, userID, opts)
var r0 model.ChannelList var r0 model.ChannelList
if rf, ok := ret.Get(0).(func(string, string, bool, int) model.ChannelList); ok { if rf, ok := ret.Get(0).(func(string, string, *model.ChannelSearchOpts) model.ChannelList); ok {
r0 = rf(teamID, userID, includeDeleted, lastDeleteAt) r0 = rf(teamID, userID, opts)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelList) r0 = ret.Get(0).(model.ChannelList)
@@ -688,8 +688,8 @@ func (_m *ChannelStore) GetChannels(teamID string, userID string, includeDeleted
} }
var r1 error var r1 error
if rf, ok := ret.Get(1).(func(string, string, bool, int) error); ok { if rf, ok := ret.Get(1).(func(string, string, *model.ChannelSearchOpts) error); ok {
r1 = rf(teamID, userID, includeDeleted, lastDeleteAt) r1 = rf(teamID, userID, opts)
} else { } else {
r1 = ret.Error(1) r1 = ret.Error(1)
} }
@@ -789,6 +789,29 @@ func (_m *ChannelStore) GetChannelsByUser(userID string, includeDeleted bool, la
return r0, r1 return r0, r1
} }
// GetChannelsWithCursor provides a mock function with given fields: teamId, userId, opts, afterChannelID
func (_m *ChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
ret := _m.Called(teamId, userId, opts, afterChannelID)
var r0 model.ChannelList
if rf, ok := ret.Get(0).(func(string, string, *model.ChannelSearchOpts, string) model.ChannelList); ok {
r0 = rf(teamId, userId, opts, afterChannelID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelList)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, *model.ChannelSearchOpts, string) error); ok {
r1 = rf(teamId, userId, opts, afterChannelID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetChannelsWithTeamDataByIds provides a mock function with given fields: channelIds, includeDeleted // GetChannelsWithTeamDataByIds provides a mock function with given fields: channelIds, includeDeleted
func (_m *ChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) { func (_m *ChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
ret := _m.Called(channelIds, includeDeleted) ret := _m.Called(channelIds, includeDeleted)
@@ -1121,6 +1144,29 @@ func (_m *ChannelStore) GetMembersForUser(teamID string, userID string) (model.C
return r0, r1 return r0, r1
} }
// GetMembersForUserWithCursor provides a mock function with given fields: userID, afterChannel, afterUser, limit, lastUpdateAt
func (_m *ChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
ret := _m.Called(userID, afterChannel, afterUser, limit, lastUpdateAt)
var r0 model.ChannelMembers
if rf, ok := ret.Get(0).(func(string, string, string, int, int) model.ChannelMembers); ok {
r0 = rf(userID, afterChannel, afterUser, limit, lastUpdateAt)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelMembers)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, string, int, int) error); ok {
r1 = rf(userID, afterChannel, afterUser, limit, lastUpdateAt)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetMembersForUserWithPagination provides a mock function with given fields: userID, page, perPage // GetMembersForUserWithPagination provides a mock function with given fields: userID, page, perPage
func (_m *ChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) { func (_m *ChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
ret := _m.Called(userID, page, perPage) ret := _m.Called(userID, page, perPage)
@@ -1144,6 +1190,29 @@ func (_m *ChannelStore) GetMembersForUserWithPagination(userID string, page int,
return r0, r1 return r0, r1
} }
// GetMembersInfoByChannelIds provides a mock function with given fields: channelIDs
func (_m *ChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
ret := _m.Called(channelIDs)
var r0 map[string][]*model.User
if rf, ok := ret.Get(0).(func([]string) map[string][]*model.User); ok {
r0 = rf(channelIDs)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(map[string][]*model.User)
}
}
var r1 error
if rf, ok := ret.Get(1).(func([]string) error); ok {
r1 = rf(channelIDs)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetMoreChannels provides a mock function with given fields: teamID, userID, offset, limit // GetMoreChannels provides a mock function with given fields: teamID, userID, offset, limit
func (_m *ChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) { func (_m *ChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
ret := _m.Called(teamID, userID, offset, limit) ret := _m.Called(teamID, userID, offset, limit)

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

@@ -1013,10 +1013,10 @@ func (s *TimerLayerChannelStore) GetChannelUnread(channelID string, userID strin
return result, err return result, err
} }
func (s *TimerLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) { func (s *TimerLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
start := timemodule.Now() start := timemodule.Now()
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt) result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
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 {
@@ -1093,6 +1093,22 @@ func (s *TimerLayerChannelStore) GetChannelsByUser(userID string, includeDeleted
return result, err return result, err
} }
func (s *TimerLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetChannelsWithCursor", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) { func (s *TimerLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
start := timemodule.Now() start := timemodule.Now()
@@ -1333,6 +1349,22 @@ func (s *TimerLayerChannelStore) GetMembersForUser(teamID string, userID string)
return result, err return result, err
} }
func (s *TimerLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetMembersForUserWithCursor", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) { func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
start := timemodule.Now() start := timemodule.Now()
@@ -1349,6 +1381,22 @@ func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string,
return result, err return result, err
} }
func (s *TimerLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetMembersInfoByChannelIds", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) { func (s *TimerLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
start := timemodule.Now() start := timemodule.Now()
@@ -2254,6 +2302,22 @@ func (s *TimerLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int
return result, err return result, err
} }
func (s *TimerLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
start := timemodule.Now()
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelMemberHistoryStore.GetChannelsLeftSince", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) { func (s *TimerLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
start := timemodule.Now() start := timemodule.Now()