[MM-21378] Add mutex to model.Post to guard against race conditions on Post.Props (#13884)
* Add mutex to model.Post to guard against race conditions on Post.Props * Rename mutex * Add GetProp() method to Post * Fix more tests * Fix flaky test Benchmarks: BenchmarkPostPropsGet_indirect BenchmarkPostPropsGet_indirect-2 85026746 13.0 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_indirect-4 90273747 13.0 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_indirect-8 88324293 13.0 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_indirect-16 91427720 13.1 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_direct BenchmarkPostPropsGet_direct-2 1000000000 0.242 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_direct-4 1000000000 0.241 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_direct-8 1000000000 0.240 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsGet_direct-16 1000000000 0.241 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsAdd_indirect BenchmarkPostPropsAdd_indirect-2 5602224 203 ns/op 336 B/op 2 allocs/op BenchmarkPostPropsAdd_indirect-4 5959496 206 ns/op 336 B/op 2 allocs/op BenchmarkPostPropsAdd_indirect-8 5833999 205 ns/op 336 B/op 2 allocs/op BenchmarkPostPropsAdd_indirect-16 5802493 225 ns/op 336 B/op 2 allocs/op BenchmarkPostPropsAdd_direct BenchmarkPostPropsAdd_direct-2 100000000 11.3 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsAdd_direct-4 100000000 11.3 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsAdd_direct-8 100000000 11.6 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsAdd_direct-16 99840794 11.4 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsDel_indirect BenchmarkPostPropsDel_indirect-2 18824002 61.9 ns/op 48 B/op 1 allocs/op BenchmarkPostPropsDel_indirect-4 19470736 63.8 ns/op 48 B/op 1 allocs/op BenchmarkPostPropsDel_indirect-8 17640460 65.3 ns/op 48 B/op 1 allocs/op BenchmarkPostPropsDel_indirect-16 18692962 65.4 ns/op 48 B/op 1 allocs/op BenchmarkPostPropsDel_direct BenchmarkPostPropsDel_direct-2 516257440 2.34 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsDel_direct-4 514865216 2.43 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsDel_direct-8 511330477 2.37 ns/op 0 B/op 0 allocs/op BenchmarkPostPropsDel_direct-16 499504010 2.38 ns/op 0 B/op 0 allocs/op
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
9e580361c2
Коммит
1e53fe85ad
@@ -433,9 +433,9 @@ func (s *SqlPostStore) Delete(postId string, time int64, deleteByID string) *mod
|
||||
return appErr(err.Error())
|
||||
}
|
||||
|
||||
post.Props[model.POST_PROPS_DELETE_BY] = deleteByID
|
||||
post.AddProp(model.POST_PROPS_DELETE_BY, deleteByID)
|
||||
|
||||
_, err = s.GetMaster().Exec("UPDATE Posts SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt, Props = :Props WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": postId, "RootId": postId, "Props": model.StringInterfaceToJson(post.Props)})
|
||||
_, err = s.GetMaster().Exec("UPDATE Posts SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt, Props = :Props WHERE Id = :Id OR RootId = :RootId", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": postId, "RootId": postId, "Props": model.StringInterfaceToJson(post.GetProps())})
|
||||
if err != nil {
|
||||
return appErr(err.Error())
|
||||
}
|
||||
|
||||
@@ -733,7 +733,7 @@ func testEditExportMessage(t *testing.T, ss store.Store) {
|
||||
|
||||
//user 1 edits the previous post
|
||||
post1e := &model.Post{}
|
||||
*post1e = *post1
|
||||
post1e = post1.Clone()
|
||||
post1e.Message = "edit " + post1.Message
|
||||
|
||||
post1e, err = ss.Post().Update(post1e, post1)
|
||||
@@ -845,7 +845,7 @@ func testEditAfterExportMessage(t *testing.T, ss store.Store) {
|
||||
postEditTime := post1.UpdateAt + 1
|
||||
//user 1 edits the previous post
|
||||
post1e := &model.Post{}
|
||||
*post1e = *post1
|
||||
post1e = post1.Clone()
|
||||
post1e.EditAt = postEditTime
|
||||
post1e.Message = "edit " + post1.Message
|
||||
post1e, err = ss.Post().Update(post1e, post1)
|
||||
|
||||
@@ -259,16 +259,16 @@ func testFileInfoGetForUser(t *testing.T, ss store.Store) {
|
||||
}
|
||||
|
||||
func testFileInfoGetWithOptions(t *testing.T, ss store.Store) {
|
||||
makePost := func(chId string, user string) model.Post {
|
||||
makePost := func(chId string, user string) *model.Post {
|
||||
post := model.Post{}
|
||||
post.ChannelId = chId
|
||||
post.UserId = user
|
||||
_, err := ss.Post().Save(&post)
|
||||
require.Nil(t, err)
|
||||
return post
|
||||
return &post
|
||||
}
|
||||
|
||||
makeFile := func(post model.Post, user string, createAt int64, idPrefix string) model.FileInfo {
|
||||
makeFile := func(post *model.Post, user string, createAt int64, idPrefix string) model.FileInfo {
|
||||
id := model.NewId()
|
||||
id = idPrefix + id[1:] // hacky way to get sortable Ids to confirm secondary Id sort works
|
||||
fileInfo := model.FileInfo{
|
||||
@@ -298,10 +298,10 @@ func testFileInfoGetWithOptions(t *testing.T, ss store.Store) {
|
||||
post2_2 := makePost(channelId3, userId2)
|
||||
|
||||
epoch := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
file1_1 := makeFile(post1_1, userId1, epoch.AddDate(0, 0, 1).Unix(), "a") // file 1 by user 1
|
||||
file1_2 := makeFile(post1_2, userId1, epoch.AddDate(0, 0, 2).Unix(), "b") // file 2 by user 1
|
||||
file1_3 := makeFile(model.Post{}, userId1, epoch.AddDate(0, 0, 3).Unix(), "c") // file that is not attached to a post
|
||||
file2_1 := makeFile(post2_1, userId2, epoch.AddDate(0, 0, 4).Unix(), "d") // file 2 by user 1
|
||||
file1_1 := makeFile(post1_1, userId1, epoch.AddDate(0, 0, 1).Unix(), "a") // file 1 by user 1
|
||||
file1_2 := makeFile(post1_2, userId1, epoch.AddDate(0, 0, 2).Unix(), "b") // file 2 by user 1
|
||||
file1_3 := makeFile(&model.Post{}, userId1, epoch.AddDate(0, 0, 3).Unix(), "c") // file that is not attached to a post
|
||||
file2_1 := makeFile(post2_1, userId2, epoch.AddDate(0, 0, 4).Unix(), "d") // file 2 by user 1
|
||||
file2_2 := makeFile(post2_2, userId2, epoch.AddDate(0, 0, 5).Unix(), "e")
|
||||
|
||||
// delete a file
|
||||
|
||||
@@ -88,6 +88,8 @@ func testPostStoreSave(t *testing.T, ss store.Store) {
|
||||
_, err := ss.Post().Save(&rootPost)
|
||||
require.Nil(t, err)
|
||||
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
|
||||
replyPost := model.Post{}
|
||||
replyPost.ChannelId = rootPost.ChannelId
|
||||
replyPost.UserId = model.NewId()
|
||||
@@ -410,8 +412,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
|
||||
|
||||
require.Equal(t, ro1.Message, o1.Message, "Failed to save/get")
|
||||
|
||||
o1a := &model.Post{}
|
||||
*o1a = *ro1
|
||||
o1a := ro1.Clone()
|
||||
o1a.Message = ro1.Message + "BBBBBBBBBB"
|
||||
_, err = ss.Post().Update(o1a, ro1)
|
||||
require.Nil(t, err)
|
||||
@@ -422,8 +423,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
|
||||
ro1a := r1.Posts[o1.Id]
|
||||
require.Equal(t, ro1a.Message, o1a.Message, "Failed to update/get")
|
||||
|
||||
o2a := &model.Post{}
|
||||
*o2a = *ro2
|
||||
o2a := ro2.Clone()
|
||||
o2a.Message = ro2.Message + "DDDDDDD"
|
||||
_, err = ss.Post().Update(o2a, ro2)
|
||||
require.Nil(t, err)
|
||||
@@ -434,8 +434,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
|
||||
|
||||
require.Equal(t, ro2a.Message, o2a.Message, "Failed to update/get")
|
||||
|
||||
o3a := &model.Post{}
|
||||
*o3a = *ro3
|
||||
o3a := ro3.Clone()
|
||||
o3a.Message = ro3.Message + "WWWWWWW"
|
||||
_, err = ss.Post().Update(o3a, ro3)
|
||||
require.Nil(t, err)
|
||||
@@ -460,8 +459,7 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
ro4 := r4.Posts[o4.Id]
|
||||
|
||||
o4a := &model.Post{}
|
||||
*o4a = *ro4
|
||||
o4a := ro4.Clone()
|
||||
o4a.Filenames = []string{}
|
||||
o4a.FileIds = []string{model.NewId()}
|
||||
_, err = ss.Post().Update(o4a, ro4)
|
||||
@@ -497,7 +495,7 @@ func testPostStoreDelete(t *testing.T, ss store.Store) {
|
||||
|
||||
posts, _ := ss.Post().GetPostsCreatedAt(o1.ChannelId, o1.CreateAt)
|
||||
post := posts[0]
|
||||
actual := post.Props[model.POST_PROPS_DELETE_BY]
|
||||
actual := post.GetProp(model.POST_PROPS_DELETE_BY)
|
||||
|
||||
assert.Equal(t, deleteByID, actual, "Expected (*Post).Props[model.POST_PROPS_DELETE_BY] to be %v but got %v.", deleteByID, actual)
|
||||
|
||||
@@ -2291,16 +2289,13 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, ro5.Filenames, o5.Filenames, "Failed to save/get")
|
||||
|
||||
t.Run("overwrite changing message", func(t *testing.T) {
|
||||
o1a := &model.Post{}
|
||||
*o1a = *ro1
|
||||
o1a := ro1.Clone()
|
||||
o1a.Message = ro1.Message + "BBBBBBBBBB"
|
||||
|
||||
o2a := &model.Post{}
|
||||
*o2a = *ro2
|
||||
o2a := ro2.Clone()
|
||||
o2a.Message = ro2.Message + "DDDDDDD"
|
||||
|
||||
o3a := &model.Post{}
|
||||
*o3a = *ro3
|
||||
o3a := ro3.Clone()
|
||||
o3a.Message = ro3.Message + "WWWWWWW"
|
||||
|
||||
_, err = ss.Post().OverwriteMultiple([]*model.Post{o1a, o2a, o3a})
|
||||
@@ -2324,13 +2319,11 @@ func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) {
|
||||
})
|
||||
|
||||
t.Run("overwrite clearing filenames", func(t *testing.T) {
|
||||
o4a := &model.Post{}
|
||||
*o4a = *ro4
|
||||
o4a := ro4.Clone()
|
||||
o4a.Filenames = []string{}
|
||||
o4a.FileIds = []string{model.NewId()}
|
||||
|
||||
o5a := &model.Post{}
|
||||
*o5a = *ro5
|
||||
o5a := ro5.Clone()
|
||||
o5a.Filenames = []string{}
|
||||
o5a.FileIds = []string{}
|
||||
|
||||
@@ -2406,20 +2399,17 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, ro4.Message, o4.Message, "Failed to save/get")
|
||||
|
||||
t.Run("overwrite changing message", func(t *testing.T) {
|
||||
o1a := &model.Post{}
|
||||
*o1a = *ro1
|
||||
o1a := ro1.Clone()
|
||||
o1a.Message = ro1.Message + "BBBBBBBBBB"
|
||||
_, err = ss.Post().Overwrite(o1a)
|
||||
require.Nil(t, err)
|
||||
|
||||
o2a := &model.Post{}
|
||||
*o2a = *ro2
|
||||
o2a := ro2.Clone()
|
||||
o2a.Message = ro2.Message + "DDDDDDD"
|
||||
_, err = ss.Post().Overwrite(o2a)
|
||||
require.Nil(t, err)
|
||||
|
||||
o3a := &model.Post{}
|
||||
*o3a = *ro3
|
||||
o3a := ro3.Clone()
|
||||
o3a.Message = ro3.Message + "WWWWWWW"
|
||||
_, err = ss.Post().Overwrite(o3a)
|
||||
require.Nil(t, err)
|
||||
@@ -2442,8 +2432,7 @@ func testPostStoreOverwrite(t *testing.T, ss store.Store) {
|
||||
})
|
||||
|
||||
t.Run("overwrite clearing filenames", func(t *testing.T) {
|
||||
o4a := &model.Post{}
|
||||
*o4a = *ro4
|
||||
o4a := ro4.Clone()
|
||||
o4a.Filenames = []string{}
|
||||
o4a.FileIds = []string{model.NewId()}
|
||||
_, err = ss.Post().Overwrite(o4a)
|
||||
@@ -2863,8 +2852,7 @@ func testPostStoreGetDirectPostParentsForExportAfterDeleted(t *testing.T, ss sto
|
||||
p1, err = ss.Post().Save(p1)
|
||||
require.Nil(t, err)
|
||||
|
||||
o1a := &model.Post{}
|
||||
*o1a = *p1
|
||||
o1a := p1.Clone()
|
||||
o1a.DeleteAt = 1
|
||||
o1a.Message = p1.Message + "BBBBBBBBBB"
|
||||
_, err = ss.Post().Update(o1a, p1)
|
||||
|
||||
Ссылка в новой задаче
Block a user