MM-38164: Paginate the GetPostThread API (#19485)

We implement a cursor based pagination model
to page through the posts in a given thread.

The cursor is a combination of the post.CreateAt+
post.Id to differentiate multiple posts in a given
timestamp.

Some additional parameters like direction, fromPost,
fromCreateAt and perPage were introduced to implement
this.

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2022-03-24 12:51:41 +05:30
коммит произвёл GitHub
родитель ad5f57b161
Коммит c1f3827801
24 изменённых файлов: 470 добавлений и 112 удалений

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

@@ -5396,7 +5396,7 @@ func (s *OpenTracingLayerPostStore) DeleteOrphanedRows(limit int) (int64, error)
return result, err
}
func (s *OpenTracingLayerPostStore) Get(ctx context.Context, id string, skipFetchThreads bool, collapsedThreads bool, collapsedThreadsExtended bool, userID string) (*model.PostList, error) {
func (s *OpenTracingLayerPostStore) Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "PostStore.Get")
s.Root.Store.SetContext(newCtx)
@@ -5405,7 +5405,7 @@ func (s *OpenTracingLayerPostStore) Get(ctx context.Context, id string, skipFetc
}()
defer span.Finish()
result, err := s.PostStore.Get(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
result, err := s.PostStore.Get(ctx, id, opts, userID)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)

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

@@ -6121,11 +6121,11 @@ func (s *RetryLayerPostStore) DeleteOrphanedRows(limit int) (int64, error) {
}
func (s *RetryLayerPostStore) Get(ctx context.Context, id string, skipFetchThreads bool, collapsedThreads bool, collapsedThreadsExtended bool, userID string) (*model.PostList, error) {
func (s *RetryLayerPostStore) Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error) {
tries := 0
for {
result, err := s.PostStore.Get(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
result, err := s.PostStore.Get(ctx, id, opts, userID)
if err == nil {
return result, nil
}

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

@@ -110,7 +110,10 @@ func (s SearchPostStore) Delete(postId string, date int64, deletedByID string) e
err := s.PostStore.Delete(postId, date, deletedByID)
if err == nil {
postList, err2 := s.PostStore.Get(context.Background(), postId, true, false, false, "")
opts := model.GetPostsOptions{
SkipFetchThreads: true,
}
postList, err2 := s.PostStore.Get(context.Background(), postId, opts, "")
if postList != nil && len(postList.Order) > 0 {
if err2 != nil {
s.deletePostIndex(postList.Posts[postList.Order[0]])

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

@@ -547,7 +547,7 @@ func (s *SqlPostStore) buildFlaggedPostChannelFilterClause(channelId string, que
return "AND ChannelId = ?", append(queryParams, channelId)
}
func (s *SqlPostStore) getPostWithCollapsedThreads(id, userID string, extended bool) (*model.PostList, error) {
func (s *SqlPostStore) getPostWithCollapsedThreads(id, userID string, opts model.GetPostsOptions) (*model.PostList, error) {
if id == "" {
return nil, store.NewErrInvalidInput("Post", "id", id)
}
@@ -582,12 +582,71 @@ func (s *SqlPostStore) getPostWithCollapsedThreads(id, userID string, extended b
}
posts := []*model.Post{}
err = s.GetReplicaX().Select(&posts, "SELECT * FROM Posts WHERE Posts.RootId = ? AND DeleteAt = 0", id)
query := s.getQueryBuilder().
Select("*").
From("Posts").
Where(sq.Eq{
"RootId": id,
"DeleteAt": 0,
})
var sort string
if opts.Direction != "" {
if opts.Direction == "up" {
sort = "DESC"
} else if opts.Direction == "down" {
sort = "ASC"
}
}
if sort != "" {
query = query.OrderBy("CreateAt " + sort + ", Id " + sort)
}
if opts.FromPost != "" && opts.FromCreateAt != 0 {
if opts.Direction == "down" {
query = query.Where(sq.Or{
sq.Gt{"Posts.CreateAt": opts.FromCreateAt},
sq.And{
sq.Eq{"Posts.CreateAt": opts.FromCreateAt},
sq.Gt{"Posts.Id": opts.FromPost},
},
})
} else {
query = query.Where(sq.Or{
sq.Lt{"Posts.CreateAt": opts.FromCreateAt},
sq.And{
sq.Eq{"Posts.CreateAt": opts.FromCreateAt},
sq.Lt{"Posts.Id": opts.FromPost},
},
})
}
}
if opts.PerPage != 0 {
query = query.Limit(uint64(opts.PerPage + 1))
}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "getPostWithCollapsedThreads_Tosql")
}
err = s.GetReplicaX().Select(&posts, sql, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to find Posts for thread %s", id)
}
list, err := s.prepareThreadedResponse([]*postWithExtra{&post}, extended, false)
var hasNext bool
if opts.PerPage != 0 {
if len(posts) == opts.PerPage+1 {
hasNext = true
}
}
if hasNext {
// Shave off the last item.
posts = posts[:len(posts)-1]
}
list, err := s.prepareThreadedResponse([]*postWithExtra{&post}, opts.CollapsedThreadsExtended, false)
if err != nil {
return nil, err
}
@@ -595,12 +654,14 @@ func (s *SqlPostStore) getPostWithCollapsedThreads(id, userID string, extended b
list.AddPost(p)
list.AddOrder(p.Id)
}
list.HasNext = hasNext
return list, nil
}
func (s *SqlPostStore) Get(ctx context.Context, id string, skipFetchThreads, collapsedThreads, collapsedThreadsExtended bool, userID string) (*model.PostList, error) {
if collapsedThreads {
return s.getPostWithCollapsedThreads(id, userID, collapsedThreadsExtended)
func (s *SqlPostStore) Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error) {
if opts.CollapsedThreads {
return s.getPostWithCollapsedThreads(id, userID, opts)
}
pl := model.NewPostList()
@@ -620,7 +681,7 @@ func (s *SqlPostStore) Get(ctx context.Context, id string, skipFetchThreads, col
}
pl.AddPost(&post)
pl.AddOrder(id)
if !skipFetchThreads {
if !opts.SkipFetchThreads {
rootId := post.RootId
if rootId == "" {
@@ -631,16 +692,78 @@ func (s *SqlPostStore) Get(ctx context.Context, id string, skipFetchThreads, col
return nil, errors.Wrapf(err, "invalid rootId with value=%s", rootId)
}
query := s.getQueryBuilder().
Select("p.*, (SELECT count(*) FROM Posts WHERE Posts.RootId = (CASE WHEN p.RootId = '' THEN p.Id ELSE p.RootId END) AND Posts.DeleteAt = 0) as ReplyCount").
From("Posts p").
Where(sq.Or{
sq.Eq{"p.Id": rootId},
sq.Eq{"p.RootId": rootId},
}).
Where(sq.Eq{"p.DeleteAt": 0})
var sort string
if opts.Direction != "" {
if opts.Direction == "up" {
sort = "DESC"
} else if opts.Direction == "down" {
sort = "ASC"
}
}
if sort != "" {
query = query.OrderBy("CreateAt " + sort + ", Id " + sort)
}
if opts.FromPost != "" && opts.FromCreateAt != 0 {
if opts.Direction == "down" {
query = query.Where(sq.Or{
sq.Gt{"p.CreateAt": opts.FromCreateAt},
sq.And{
sq.Eq{"p.CreateAt": opts.FromCreateAt},
sq.Gt{"p.Id": opts.FromPost},
},
})
} else {
query = query.Where(sq.Or{
sq.Lt{"p.CreateAt": opts.FromCreateAt},
sq.And{
sq.Eq{"p.CreateAt": opts.FromCreateAt},
sq.Lt{"p.Id": opts.FromPost},
},
})
}
}
if opts.PerPage != 0 {
query = query.Limit(uint64(opts.PerPage + 1))
}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Get_Tosql")
}
posts := []*model.Post{}
err = s.GetReplicaX().Select(&posts, "SELECT *, (SELECT count(*) FROM Posts WHERE Posts.RootId = (CASE WHEN p.RootId = '' THEN p.Id ELSE p.RootId END) AND Posts.DeleteAt = 0) as ReplyCount FROM Posts p WHERE (Id = ? OR RootId = ?) AND DeleteAt = 0", rootId, rootId)
err = s.GetReplicaX().Select(&posts, sql, args...)
if err != nil {
return nil, errors.Wrap(err, "failed to find Posts")
}
var hasNext bool
if opts.PerPage != 0 {
if len(posts) == opts.PerPage+1 {
hasNext = true
}
}
if hasNext {
// Shave off the last item
posts = posts[:len(posts)-1]
}
for _, p := range posts {
pl.AddPost(p)
pl.AddOrder(p.Id)
}
pl.HasNext = hasNext
}
return pl, nil
}

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

@@ -322,7 +322,7 @@ type PostStore interface {
SaveMultiple(posts []*model.Post) ([]*model.Post, int, error)
Save(post *model.Post) (*model.Post, error)
Update(newPost *model.Post, oldPost *model.Post) (*model.Post, error)
Get(ctx context.Context, id string, skipFetchThreads, collapsedThreads, collapsedThreadsExtended bool, userID string) (*model.PostList, error)
Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error)
GetSingle(id string, inclDeleted bool) (*model.Post, error)
Delete(postID string, time int64, deleteByID string) error
PermanentDeleteByUser(userID string) error

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

@@ -123,13 +123,13 @@ func (_m *PostStore) DeleteOrphanedRows(limit int) (int64, error) {
return r0, r1
}
// Get provides a mock function with given fields: ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID
func (_m *PostStore) Get(ctx context.Context, id string, skipFetchThreads bool, collapsedThreads bool, collapsedThreadsExtended bool, userID string) (*model.PostList, error) {
ret := _m.Called(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
// Get provides a mock function with given fields: ctx, id, opts, userID
func (_m *PostStore) Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error) {
ret := _m.Called(ctx, id, opts, userID)
var r0 *model.PostList
if rf, ok := ret.Get(0).(func(context.Context, string, bool, bool, bool, string) *model.PostList); ok {
r0 = rf(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
if rf, ok := ret.Get(0).(func(context.Context, string, model.GetPostsOptions, string) *model.PostList); ok {
r0 = rf(ctx, id, opts, userID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.PostList)
@@ -137,8 +137,8 @@ func (_m *PostStore) Get(ctx context.Context, id string, skipFetchThreads bool,
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string, bool, bool, bool, string) error); ok {
r1 = rf(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
if rf, ok := ret.Get(1).(func(context.Context, string, model.GetPostsOptions, string) error); ok {
r1 = rf(ctx, id, opts, userID)
} else {
r1 = ret.Error(1)
}

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

@@ -491,14 +491,14 @@ func testPostStoreGet(t *testing.T, ss store.Store) {
etag2 := ss.Post().GetEtag(o1.ChannelId, false, false)
require.Equal(t, 0, strings.Index(etag2, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)), "Invalid Etag")
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
_, err = ss.Post().Get(context.Background(), "123", false, false, false, "")
_, err = ss.Post().Get(context.Background(), "123", model.GetPostsOptions{}, "")
require.Error(t, err, "Missing id should have failed")
_, err = ss.Post().Get(context.Background(), "", false, false, false, "")
_, err = ss.Post().Get(context.Background(), "", model.GetPostsOptions{}, "")
require.Error(t, err, "should fail for blank post ids")
}
@@ -515,7 +515,10 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
UpdateFollowing: true,
})
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, true, false, o1.UserId)
opts := model.GetPostsOptions{
CollapsedThreads: true,
}
r1, err := ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
require.True(t, *r1.Posts[o1.Id].IsFollowing)
@@ -533,7 +536,10 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
UpdateFollowing: true,
})
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, true, false, o1.UserId)
opts := model.GetPostsOptions{
CollapsedThreads: true,
}
r1, err := ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
require.False(t, *r1.Posts[o1.Id].IsFollowing)
@@ -546,11 +552,113 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, true, false, o1.UserId)
opts := model.GetPostsOptions{
CollapsedThreads: true,
}
r1, err := ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
require.Nil(t, r1.Posts[o1.Id].IsFollowing)
})
t.Run("Pagination", func(t *testing.T) {
o1, err := ss.Post().Save(&model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()})
require.NoError(t, err)
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
require.NoError(t, err)
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
require.NoError(t, err)
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
require.NoError(t, err)
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
require.NoError(t, err)
opts := model.GetPostsOptions{
CollapsedThreads: true,
PerPage: 2,
Direction: "down",
}
r1, err := ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.True(t, r1.HasNext)
lastPostID := r1.Order[len(r1.Order)-1]
lastPostCreateAt := r1.Posts[lastPostID].CreateAt
opts = model.GetPostsOptions{
CollapsedThreads: true,
PerPage: 2,
Direction: "down",
FromPost: lastPostID,
FromCreateAt: lastPostCreateAt,
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.GreaterOrEqual(t, r1.Posts[r1.Order[len(r1.Order)-1]].CreateAt, lastPostCreateAt)
assert.False(t, r1.HasNext)
// Going from bottom to top now.
firstPostCreateAt := r1.Posts[r1.Order[1]].CreateAt
opts = model.GetPostsOptions{
CollapsedThreads: true,
PerPage: 2,
Direction: "up",
FromPost: r1.Order[1],
FromCreateAt: firstPostCreateAt,
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.LessOrEqual(t, r1.Posts[r1.Order[1]].CreateAt, firstPostCreateAt)
assert.False(t, r1.HasNext)
// Non-CRT mode
opts = model.GetPostsOptions{
CollapsedThreads: false,
PerPage: 2,
Direction: "down",
SkipFetchThreads: false,
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.True(t, r1.HasNext)
lastPostID = r1.Order[len(r1.Order)-1]
lastPostCreateAt = r1.Posts[lastPostID].CreateAt
opts = model.GetPostsOptions{
CollapsedThreads: false,
PerPage: 3,
Direction: "down",
FromPost: lastPostID,
FromCreateAt: lastPostCreateAt,
SkipFetchThreads: false,
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 4) // including the root post
assert.GreaterOrEqual(t, r1.Posts[r1.Order[len(r1.Order)-1]].CreateAt, lastPostCreateAt)
assert.False(t, r1.HasNext)
// Going from bottom to top now.
firstPostCreateAt = r1.Posts[r1.Order[1]].CreateAt
opts = model.GetPostsOptions{
CollapsedThreads: false,
PerPage: 2,
Direction: "up",
FromPost: r1.Order[1],
FromCreateAt: firstPostCreateAt,
SkipFetchThreads: false,
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId)
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.LessOrEqual(t, r1.Posts[r1.Order[1]].CreateAt, firstPostCreateAt)
assert.False(t, r1.HasNext)
})
}
func testPostStoreGetSingle(t *testing.T, ss store.Store) {
@@ -635,15 +743,15 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
o3, err = ss.Post().Save(o3)
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1 := r1.Posts[o1.Id]
r2, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r2, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2 := r2.Posts[o2.Id]
r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err := ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3 := r3.Posts[o3.Id]
@@ -654,7 +762,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
_, err = ss.Post().Update(o1a, ro1)
require.NoError(t, err)
r1, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1a := r1.Posts[o1.Id]
@@ -665,7 +773,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
_, err = ss.Post().Update(o2a, ro2)
require.NoError(t, err)
r2, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r2, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2a := r2.Posts[o2.Id]
@@ -676,7 +784,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
_, err = ss.Post().Update(o3a, ro3)
require.NoError(t, err)
r3, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3a := r3.Posts[o3.Id]
@@ -692,7 +800,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
})
require.NoError(t, err)
r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, err := ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro4 := r4.Posts[o4.Id]
@@ -702,7 +810,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
_, err = ss.Post().Update(o4a, ro4)
require.NoError(t, err)
r4, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, err = ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro4a := r4.Posts[o4.Id]
@@ -723,7 +831,7 @@ func testPostStoreDelete(t *testing.T, ss store.Store) {
o1, err := ss.Post().Save(o1)
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
@@ -736,7 +844,7 @@ func testPostStoreDelete(t *testing.T, ss store.Store) {
assert.Equal(t, deleteByID, actual, "Expected (*Post).Props[model.PostPropsDeleteBy] to be %v but got %v.", deleteByID, actual)
r3, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r3, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Missing id should have failed - PostList %v", r3)
etag2 := ss.Post().GetEtag(o1.ChannelId, false, false)
@@ -762,10 +870,10 @@ func testPostStoreDelete1Level(t *testing.T, ss store.Store) {
err = ss.Post().Delete(o1.Id, model.GetMillis(), "")
require.NoError(t, err)
_, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
}
@@ -803,16 +911,16 @@ func testPostStoreDelete2Level(t *testing.T, ss store.Store) {
err = ss.Post().Delete(o1.Id, model.GetMillis(), "")
require.NoError(t, err)
_, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
}
@@ -878,10 +986,10 @@ func testPostStorePermDelete1Level(t *testing.T, ss store.Store) {
require.EqualValues(t, 0, thread.ReplyCount)
require.EqualValues(t, model.StringArray{}, thread.Participants)
_, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err, "Deleted id shouldn't have failed")
_, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
thread, err = ss.Thread().Get(o5.Id)
@@ -895,16 +1003,16 @@ func testPostStorePermDelete1Level(t *testing.T, ss store.Store) {
require.NoError(t, err)
require.Nil(t, thread)
_, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o5.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o5.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o6.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o6.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
}
@@ -934,13 +1042,13 @@ func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) {
err2 := ss.Post().PermanentDeleteByUser(o1.UserId)
require.NoError(t, err2)
_, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err, "Deleted id should have failed")
}
@@ -968,7 +1076,7 @@ func testPostStoreGetWithChildren(t *testing.T, ss store.Store) {
o3, err = ss.Post().Save(o3)
require.NoError(t, err)
pl, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
pl, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Len(t, pl.Posts, 3, "invalid returned post")
@@ -976,7 +1084,7 @@ func testPostStoreGetWithChildren(t *testing.T, ss store.Store) {
dErr := ss.Post().Delete(o3.Id, model.GetMillis(), "")
require.NoError(t, dErr)
pl, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
pl, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Len(t, pl.Posts, 2, "invalid returned post")
@@ -984,7 +1092,7 @@ func testPostStoreGetWithChildren(t *testing.T, ss store.Store) {
dErr = ss.Post().Delete(o2.Id, model.GetMillis(), "")
require.NoError(t, dErr)
pl, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
pl, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Len(t, pl.Posts, 1, "invalid returned post")
@@ -2579,23 +2687,23 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) {
})
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1 := r1.Posts[o1.Id]
r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
r2, err := ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2 := r2.Posts[o2.Id]
r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err := ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3 := r3.Posts[o3.Id]
r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, err := ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro4 := r4.Posts[o4.Id]
r5, err := ss.Post().Get(context.Background(), o5.Id, false, false, false, "")
r5, err := ss.Post().Get(context.Background(), o5.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro5 := r5.Posts[o5.Id]
@@ -2621,15 +2729,15 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) {
require.NoError(t, err)
require.Equal(t, -1, errIdx)
r1, nErr := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, nErr := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, nErr)
ro1a := r1.Posts[o1.Id]
r2, nErr = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r2, nErr = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, nErr)
ro2a := r2.Posts[o2.Id]
r3, nErr = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, nErr = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, nErr)
ro3a := r3.Posts[o3.Id]
@@ -2651,11 +2759,11 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) {
require.NoError(t, err)
require.Equal(t, -1, errIdx)
r4, nErr := ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, nErr := ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, nErr)
ro4a := r4.Posts[o4.Id]
r5, nErr = ss.Post().Get(context.Background(), o5.Id, false, false, false, "")
r5, nErr = ss.Post().Get(context.Background(), o5.Id, model.GetPostsOptions{}, "")
require.NoError(t, nErr)
ro5a := r5.Posts[o5.Id]
@@ -2697,19 +2805,19 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) {
})
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1 := r1.Posts[o1.Id]
r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
r2, err := ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2 := r2.Posts[o2.Id]
r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err := ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3 := r3.Posts[o3.Id]
r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, err := ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro4 := r4.Posts[o4.Id]
@@ -2734,15 +2842,15 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) {
_, err = ss.Post().Overwrite(o3a)
require.NoError(t, err)
r1, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1a := r1.Posts[o1.Id]
r2, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r2, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2a := r2.Posts[o2.Id]
r3, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3a := r3.Posts[o3.Id]
@@ -2758,7 +2866,7 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) {
_, err = ss.Post().Overwrite(o4a)
require.NoError(t, err)
r4, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "")
r4, err = ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro4a := r4.Posts[o4.Id]
@@ -2789,15 +2897,15 @@ func testPostStoreGetPostsByIds(t *testing.T, ss store.Store) {
o3, err = ss.Post().Save(o3)
require.NoError(t, err)
r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro1 := r1.Posts[o1.Id]
r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
r2, err := ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro2 := r2.Posts[o2.Id]
r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
r3, err := ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
ro3 := r3.Posts[o3.Id]
@@ -2918,13 +3026,13 @@ func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) {
_, _, err = ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2000, 1000, model.RetentionPolicyCursor{})
require.NoError(t, err)
_, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Should have not found post 1 after purge")
_, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Should have not found post 2 after purge")
_, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "")
_, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err, "Should have found post 3 after purge")
t.Run("with pagination", func(t *testing.T) {
@@ -2968,13 +3076,13 @@ func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) {
_, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2000, 1000, model.RetentionPolicyCursor{})
require.NoError(t, err2)
_, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "")
_, err2 = ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.NoError(t, err2, "global policy should have been ignored due to granular policy")
nowMillis := post.CreateAt + *channelPolicy.PostDuration*24*60*60*1000 + 1
_, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{})
require.NoError(t, err2)
_, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "")
_, err2 = ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.Error(t, err2, "post should have been deleted by channel policy")
// Create a team policy which is stricter than the channel policy
@@ -2993,7 +3101,7 @@ func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) {
nowMillis = post.CreateAt + *teamPolicy.PostDuration*24*60*60*1000 + 1
_, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{})
require.NoError(t, err2)
_, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "")
_, err2 = ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.NoError(t, err2, "channel policy should have overridden team policy")
// Delete channel policy and re-run team policy
@@ -3005,7 +3113,7 @@ func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) {
_, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{})
require.NoError(t, err2)
_, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "")
_, err2 = ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.Error(t, err2, "post should have been deleted by team policy")
err2 = ss.RetentionPolicy().RemoveTeams(teamPolicy.ID, []string{team.Id})

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

@@ -55,7 +55,7 @@ func testReactionSave(t *testing.T, ss store.Store) {
assert.Zero(t, saved.DeleteAt, "should've saved reaction delete_at with zero value and returned it")
var secondUpdateAt int64
postList, err := ss.Post().Get(context.Background(), reaction1.PostId, false, false, false, "")
postList, err := ss.Post().Get(context.Background(), reaction1.PostId, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.True(t, postList.Posts[post.Id].HasReactions, "should've set HasReactions = true on post")
@@ -79,7 +79,7 @@ func testReactionSave(t *testing.T, ss store.Store) {
_, nErr = ss.Reaction().Save(reaction2)
require.NoError(t, nErr)
postList, err = ss.Post().Get(context.Background(), reaction2.PostId, false, false, false, "")
postList, err = ss.Post().Get(context.Background(), reaction2.PostId, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.NotEqual(t, postList.Posts[post.Id].UpdateAt, secondUpdateAt, "should've marked post as updated even if HasReactions doesn't change")
@@ -129,7 +129,7 @@ func testReactionDelete(t *testing.T, ss store.Store) {
_, nErr := ss.Reaction().Save(reaction)
require.NoError(t, nErr)
result, err := ss.Post().Get(context.Background(), reaction.PostId, false, false, false, "")
result, err := ss.Post().Get(context.Background(), reaction.PostId, model.GetPostsOptions{}, "")
require.NoError(t, err)
firstUpdateAt := result.Posts[post.Id].UpdateAt
@@ -142,7 +142,7 @@ func testReactionDelete(t *testing.T, ss store.Store) {
assert.Empty(t, reactions, "should've deleted reaction")
postList, err := ss.Post().Get(context.Background(), post.Id, false, false, false, "")
postList, err := ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.False(t, postList.Posts[post.Id].HasReactions, "should've set HasReactions = false on post")
@@ -507,15 +507,15 @@ func testReactionDeleteAllWithEmojiName(t *testing.T, ss store.Store, s SqlStore
assert.Empty(t, returned, "should've only removed reactions with emoji name")
// check that the posts are updated
postList, err := ss.Post().Get(context.Background(), post.Id, false, false, false, "")
postList, err := ss.Post().Get(context.Background(), post.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.True(t, postList.Posts[post.Id].HasReactions, "post should still have reactions")
postList, err = ss.Post().Get(context.Background(), post2.Id, false, false, false, "")
postList, err = ss.Post().Get(context.Background(), post2.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.True(t, postList.Posts[post2.Id].HasReactions, "post should still have reactions")
postList, err = ss.Post().Get(context.Background(), post3.Id, false, false, false, "")
postList, err = ss.Post().Get(context.Background(), post3.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
assert.False(t, postList.Posts[post3.Id].HasReactions, "post shouldn't have reactions any more")

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

@@ -80,7 +80,10 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) {
newPosts, errIdx, err3 := ss.Post().SaveMultiple([]*model.Post{&o2, &o3, &o4})
olist, _ := ss.Post().Get(context.Background(), otmp.Id, true, false, false, "")
opts := model.GetPostsOptions{
SkipFetchThreads: true,
}
olist, _ := ss.Post().Get(context.Background(), otmp.Id, opts, "")
o1 := olist.Posts[olist.Order[0]]
newPosts = append([]*model.Post{o1}, newPosts...)

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

@@ -4890,10 +4890,10 @@ func (s *TimerLayerPostStore) DeleteOrphanedRows(limit int) (int64, error) {
return result, err
}
func (s *TimerLayerPostStore) Get(ctx context.Context, id string, skipFetchThreads bool, collapsedThreads bool, collapsedThreadsExtended bool, userID string) (*model.PostList, error) {
func (s *TimerLayerPostStore) Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string) (*model.PostList, error) {
start := timemodule.Now()
result, err := s.PostStore.Get(ctx, id, skipFetchThreads, collapsedThreads, collapsedThreadsExtended, userID)
result, err := s.PostStore.Get(ctx, id, opts, userID)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {