MM-58038: Use context to call master for DeletePost (#27098)

Calling app.DeletePost immediately after creating a post
is susceptible to replica lag because we were calling the
replica to check for the post.

We fix this by passing a context to always query master.

https://mattermost.atlassian.net/browse/MM-58038

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2024-05-24 19:35:48 +05:30
коммит произвёл GitHub
родитель 09c0eb7e7a
Коммит 6f3327ce0f
34 изменённых файлов: 94 добавлений и 93 удалений

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

@@ -6771,7 +6771,7 @@ func (s *OpenTracingLayerPostStore) GetRepliesForExport(parentID string) ([]*mod
return result, err
}
func (s *OpenTracingLayerPostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error) {
func (s *OpenTracingLayerPostStore) GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "PostStore.GetSingle")
s.Root.Store.SetContext(newCtx)
@@ -6780,7 +6780,7 @@ func (s *OpenTracingLayerPostStore) GetSingle(id string, inclDeleted bool) (*mod
}()
defer span.Finish()
result, err := s.PostStore.GetSingle(id, inclDeleted)
result, err := s.PostStore.GetSingle(rctx, id, inclDeleted)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)

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

@@ -7685,11 +7685,11 @@ func (s *RetryLayerPostStore) GetRepliesForExport(parentID string) ([]*model.Rep
}
func (s *RetryLayerPostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error) {
func (s *RetryLayerPostStore) GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error) {
tries := 0
for {
result, err := s.PostStore.GetSingle(id, inclDeleted)
result, err := s.PostStore.GetSingle(rctx, id, inclDeleted)
if err == nil {
return result, nil
}

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

@@ -23,7 +23,7 @@ func (s SearchFileInfoStore) indexFile(rctx request.CTX, file *model.FileInfo) {
if file.PostId == "" {
return
}
post, postErr := s.rootStore.Post().GetSingle(file.PostId, false)
post, postErr := s.rootStore.Post().GetSingle(rctx, file.PostId, false)
if postErr != nil {
rctx.Logger().Error("Couldn't get post for file for SearchEngine indexing.", mlog.String("post_id", file.PostId), mlog.String("search_engine", engineCopy.GetName()), mlog.String("file_info_id", file.Id), mlog.Err(postErr))
return

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

@@ -833,7 +833,7 @@ func (s *SqlPostStore) Get(ctx context.Context, id string, opts model.GetPostsOp
return pl, nil
}
func (s *SqlPostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error) {
func (s *SqlPostStore) GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error) {
query := s.getQueryBuilder().
Select("p.*").
From("Posts p").
@@ -855,7 +855,7 @@ func (s *SqlPostStore) GetSingle(id string, inclDeleted bool) (*model.Post, erro
}
var post model.Post
err = s.GetReplicaX().Get(&post, queryString, args...)
err = s.DBXFromContext(rctx.Context()).Get(&post, queryString, args...)
if err != nil {
if err == sql.ErrNoRows {
return nil, store.NewErrNotFound("Post", id)

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

@@ -945,7 +945,7 @@ func (s SqlTeamStore) UpdateMember(rctx request.CTX, member *model.TeamMember) (
}
// GetMember returns a single member of the team that matches the teamId and userId provided as parameters.
func (s SqlTeamStore) GetMember(ctx request.CTX, teamId string, userId string) (*model.TeamMember, error) {
func (s SqlTeamStore) GetMember(rctx request.CTX, teamId string, userId string) (*model.TeamMember, error) {
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": teamId}).
Where(sq.Eq{"TeamMembers.UserId": userId})
@@ -956,7 +956,7 @@ func (s SqlTeamStore) GetMember(ctx request.CTX, teamId string, userId string) (
}
var dbMember teamMemberWithSchemeRoles
err = s.DBXFromContext(ctx.Context()).Get(&dbMember, queryString, args...)
err = s.DBXFromContext(rctx.Context()).Get(&dbMember, queryString, args...)
if err != nil {
if err == sql.ErrNoRows {
return nil, store.NewErrNotFound("TeamMember", fmt.Sprintf("teamId=%s, userId=%s", teamId, userId))

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

@@ -353,7 +353,7 @@ type PostStore interface {
Save(rctx request.CTX, post *model.Post) (*model.Post, error)
Update(rctx request.CTX, newPost *model.Post, oldPost *model.Post) (*model.Post, error)
Get(ctx context.Context, id string, opts model.GetPostsOptions, userID string, sanitizeOptions map[string]bool) (*model.PostList, error)
GetSingle(id string, inclDeleted bool) (*model.Post, error)
GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error)
Delete(rctx request.CTX, postID string, timestamp int64, deleteByID string) error
PermanentDeleteByUser(rctx request.CTX, userID string) error
PermanentDeleteByChannel(rctx request.CTX, channelID string) error

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

@@ -916,9 +916,9 @@ func (_m *PostStore) GetRepliesForExport(parentID string) ([]*model.ReplyForExpo
return r0, r1
}
// GetSingle provides a mock function with given fields: id, inclDeleted
func (_m *PostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error) {
ret := _m.Called(id, inclDeleted)
// GetSingle provides a mock function with given fields: rctx, id, inclDeleted
func (_m *PostStore) GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error) {
ret := _m.Called(rctx, id, inclDeleted)
if len(ret) == 0 {
panic("no return value specified for GetSingle")
@@ -926,19 +926,19 @@ func (_m *PostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error)
var r0 *model.Post
var r1 error
if rf, ok := ret.Get(0).(func(string, bool) (*model.Post, error)); ok {
return rf(id, inclDeleted)
if rf, ok := ret.Get(0).(func(request.CTX, string, bool) (*model.Post, error)); ok {
return rf(rctx, id, inclDeleted)
}
if rf, ok := ret.Get(0).(func(string, bool) *model.Post); ok {
r0 = rf(id, inclDeleted)
if rf, ok := ret.Get(0).(func(request.CTX, string, bool) *model.Post); ok {
r0 = rf(rctx, id, inclDeleted)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.Post)
}
}
if rf, ok := ret.Get(1).(func(string, bool) error); ok {
r1 = rf(id, inclDeleted)
if rf, ok := ret.Get(1).(func(request.CTX, string, bool) error); ok {
r1 = rf(rctx, id, inclDeleted)
} else {
r1 = ret.Error(1)
}

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

@@ -56,7 +56,7 @@ func testPostAcknowledgementsStoreSave(t *testing.T, rctx request.CTX, ss store.
_, err := ss.PostAcknowledgement().Save(post.Id, userId1, 0)
require.NoError(t, err)
post, err = ss.Post().GetSingle(post.Id, false)
post, err = ss.Post().GetSingle(rctx, post.Id, false)
require.NoError(t, err)
require.Greater(t, post.UpdateAt, oldUpdateAt)
})

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

@@ -180,7 +180,7 @@ func testPostStoreSave(t *testing.T, rctx request.CTX, ss store.Store) {
_, err = ss.Post().Save(rctx, &replyPost)
require.NoError(t, err)
rrootPost, err := ss.Post().GetSingle(rootPost.Id, false)
rrootPost, err := ss.Post().GetSingle(rctx, rootPost.Id, false)
require.NoError(t, err)
assert.Greater(t, rrootPost.UpdateAt, rootPost.UpdateAt)
})
@@ -293,7 +293,7 @@ func testPostStoreSaveMultiple(t *testing.T, rctx request.CTX, ss store.Store) {
require.NoError(t, err)
require.Equal(t, -1, errIdx)
for _, post := range newPosts {
storedPost, err := ss.Post().GetSingle(post.Id, false)
storedPost, err := ss.Post().GetSingle(rctx, post.Id, false)
assert.NoError(t, err)
assert.Equal(t, post.ChannelId, storedPost.ChannelId)
assert.Equal(t, post.Message, storedPost.Message)
@@ -372,13 +372,13 @@ func testPostStoreSaveMultiple(t *testing.T, rctx request.CTX, ss store.Store) {
require.Error(t, err)
require.Equal(t, 1, errIdx)
require.Nil(t, newPosts)
storedPost, err := ss.Post().GetSingle(p3.Id, false)
storedPost, err := ss.Post().GetSingle(rctx, p3.Id, false)
assert.NoError(t, err)
assert.Equal(t, p3.ChannelId, storedPost.ChannelId)
assert.Equal(t, p3.Message, storedPost.Message)
assert.Equal(t, p3.UserId, storedPost.UserId)
storedPost, err = ss.Post().GetSingle(p4.Id, false)
storedPost, err = ss.Post().GetSingle(rctx, p4.Id, false)
assert.Error(t, err)
assert.Nil(t, storedPost)
})
@@ -407,7 +407,7 @@ func testPostStoreSaveMultiple(t *testing.T, rctx request.CTX, ss store.Store) {
_, _, err = ss.Post().SaveMultiple([]*model.Post{&rootPost, &replyPost})
require.NoError(t, err)
rrootPost, err := ss.Post().GetSingle(rootPost.Id, false)
rrootPost, err := ss.Post().GetSingle(rctx, rootPost.Id, false)
require.NoError(t, err)
assert.Equal(t, rrootPost.UpdateAt, rootPost.UpdateAt)
@@ -429,7 +429,7 @@ func testPostStoreSaveMultiple(t *testing.T, rctx request.CTX, ss store.Store) {
_, _, err = ss.Post().SaveMultiple([]*model.Post{&replyPost2, &replyPost3})
require.NoError(t, err)
rrootPost2, err := ss.Post().GetSingle(rootPost.Id, false)
rrootPost2, err := ss.Post().GetSingle(rctx, rootPost.Id, false)
require.NoError(t, err)
assert.Greater(t, rrootPost2.UpdateAt, rrootPost.UpdateAt)
})
@@ -947,21 +947,21 @@ func testPostStoreGetSingle(t *testing.T, rctx request.CTX, ss store.Store) {
err = ss.Post().Delete(rctx, o4.Id, model.GetMillis(), o4.UserId)
require.NoError(t, err)
post, err := ss.Post().GetSingle(o1.Id, false)
post, err := ss.Post().GetSingle(rctx, o1.Id, false)
require.NoError(t, err)
require.Equal(t, post.CreateAt, o1.CreateAt, "invalid returned post")
require.Equal(t, int64(1), post.ReplyCount, "wrong replyCount computed")
_, err = ss.Post().GetSingle(o2.Id, false)
_, err = ss.Post().GetSingle(rctx, o2.Id, false)
require.Error(t, err, "should not return deleted post")
post, err = ss.Post().GetSingle(o2.Id, true)
post, err = ss.Post().GetSingle(rctx, o2.Id, true)
require.NoError(t, err)
require.Equal(t, post.CreateAt, o2.CreateAt, "invalid returned post")
require.NotZero(t, post.DeleteAt, "DeleteAt should be non-zero")
require.Zero(t, post.ReplyCount, "Post without replies should return zero ReplyCount")
_, err = ss.Post().GetSingle("123", false)
_, err = ss.Post().GetSingle(rctx, "123", false)
require.Error(t, err, "Missing id should have failed")
}

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

@@ -188,7 +188,7 @@ func testThreadStorePopulation(t *testing.T, rctx request.CTX, ss store.Store) {
thread1, err := ss.Thread().Get(newPosts[0].RootId)
require.NoError(t, err)
rrootPost, err := ss.Post().GetSingle(rootPost.Id, false)
rrootPost, err := ss.Post().GetSingle(rctx, rootPost.Id, false)
require.NoError(t, err)
require.Equal(t, rrootPost.UpdateAt, rootPost.UpdateAt)
@@ -207,7 +207,7 @@ func testThreadStorePopulation(t *testing.T, rctx request.CTX, ss store.Store) {
_, _, err = ss.Post().SaveMultiple([]*model.Post{&replyPost2, &replyPost3})
require.NoError(t, err)
rrootPost2, err := ss.Post().GetSingle(rootPost.Id, false)
rrootPost2, err := ss.Post().GetSingle(rctx, rootPost.Id, false)
require.NoError(t, err)
require.Greater(t, rrootPost2.UpdateAt, rrootPost.UpdateAt)
@@ -969,7 +969,7 @@ func testVarious(t *testing.T, rctx request.CTX, ss store.Store) {
gm1post1,
}
for i := range allPosts {
updatedPost, err := ss.Post().GetSingle(allPosts[i].Id, true)
updatedPost, err := ss.Post().GetSingle(rctx, allPosts[i].Id, true)
require.NoError(t, err)
// Fix some inconsistencies with how the post store returns posts vs. how the

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

@@ -6122,10 +6122,10 @@ func (s *TimerLayerPostStore) GetRepliesForExport(parentID string) ([]*model.Rep
return result, err
}
func (s *TimerLayerPostStore) GetSingle(id string, inclDeleted bool) (*model.Post, error) {
func (s *TimerLayerPostStore) GetSingle(rctx request.CTX, id string, inclDeleted bool) (*model.Post, error) {
start := time.Now()
result, err := s.PostStore.GetSingle(id, inclDeleted)
result, err := s.PostStore.GetSingle(rctx, id, inclDeleted)
elapsed := float64(time.Since(start)) / float64(time.Second)
if s.Root.Metrics != nil {