Fix #10963: GetDirectPostParentsForExportAfter is sync now (#11009)

Этот коммит содержится в:
Rodrigo Villablanca Vásquez
2019-05-30 17:19:14 -04:00
коммит произвёл Hanzei
родитель 76e00b406e
Коммит 9fa1622fc3
6 изменённых файлов: 108 добавлений и 108 удалений

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

@@ -552,12 +552,11 @@ func (a *App) ExportAllDirectChannels(writer io.Writer) *model.AppError {
func (a *App) ExportAllDirectPosts(writer io.Writer) *model.AppError { func (a *App) ExportAllDirectPosts(writer io.Writer) *model.AppError {
afterId := strings.Repeat("0", 26) afterId := strings.Repeat("0", 26)
for { for {
result := <-a.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, afterId) posts, err := a.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, afterId)
if result.Err != nil { if err != nil {
return result.Err return err
} }
posts := result.Data.([]*model.DirectPostForExport)
if len(posts) == 0 { if len(posts) == 0 {
break break
} }

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

@@ -407,12 +407,12 @@ func TestExportDMandGMPost(t *testing.T) {
} }
th1.App.CreatePost(p4, gmChannel, false) th1.App.CreatePost(p4, gmChannel, false)
result := <-th1.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err := th1.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts := result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
assert.Equal(t, 4, len(posts)) assert.Equal(t, 4, len(posts))
var b bytes.Buffer var b bytes.Buffer
err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") err = th1.App.BulkExport(&b, "somefile", "somePath", "someDir")
require.Nil(t, err) require.Nil(t, err)
th1.TearDown() th1.TearDown()
@@ -420,8 +420,8 @@ func TestExportDMandGMPost(t *testing.T) {
th2 := Setup(t) th2 := Setup(t)
defer th2.TearDown() defer th2.TearDown()
result = <-th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err = th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts = result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
assert.Equal(t, 0, len(posts)) assert.Equal(t, 0, len(posts))
// import the exported posts // import the exported posts
@@ -429,8 +429,8 @@ func TestExportDMandGMPost(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, i) assert.Equal(t, 0, i)
result = <-th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err = th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts = result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
// Adding some deteminism so its possible to assert on slice index // Adding some deteminism so its possible to assert on slice index
sort.Slice(posts, func(i, j int) bool { return posts[i].Message > posts[j].Message }) sort.Slice(posts, func(i, j int) bool { return posts[i].Message > posts[j].Message })
@@ -453,8 +453,8 @@ func TestExportDMPostWithSelf(t *testing.T) {
err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir")
require.Nil(t, err) require.Nil(t, err)
result := <-th1.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err := th1.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts := result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
assert.Equal(t, 1, len(posts)) assert.Equal(t, 1, len(posts))
th1.TearDown() th1.TearDown()
@@ -462,8 +462,8 @@ func TestExportDMPostWithSelf(t *testing.T) {
th2 := Setup(t) th2 := Setup(t)
defer th2.TearDown() defer th2.TearDown()
result = <-th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err = th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts = result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
assert.Equal(t, 0, len(posts)) assert.Equal(t, 0, len(posts))
// import the exported posts // import the exported posts
@@ -471,7 +471,7 @@ func TestExportDMPostWithSelf(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, i) assert.Equal(t, 0, i)
result = <-th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") posts, err = th2.App.Srv.Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
posts = result.Data.([]*model.DirectPostForExport) require.Nil(t, err)
assert.Equal(t, 0, len(posts)) assert.Equal(t, 0, len(posts))
} }

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

@@ -1330,76 +1330,72 @@ func (s *SqlPostStore) GetRepliesForExport(parentId string) store.StoreChannel {
}) })
} }
func (s *SqlPostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) store.StoreChannel { func (s *SqlPostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) ([]*model.DirectPostForExport, *model.AppError) {
return store.Do(func(result *store.StoreResult) { query := s.getQueryBuilder().
query := s.getQueryBuilder(). Select("p.*", "Users.Username as User").
Select("p.*", "Users.Username as User"). From("Posts p").
From("Posts p"). Join("Channels ON p.ChannelId = Channels.Id").
Join("Channels ON p.ChannelId = Channels.Id"). Join("Users ON p.UserId = Users.Id").
Join("Users ON p.UserId = Users.Id"). Where(sq.And{
Where(sq.And{ sq.Gt{"p.Id": afterId},
sq.Gt{"p.Id": afterId}, sq.Eq{"p.ParentId": string("")},
sq.Eq{"p.ParentId": string("")}, sq.Eq{"p.DeleteAt": int(0)},
sq.Eq{"p.DeleteAt": int(0)}, sq.Eq{"Channels.DeleteAt": int(0)},
sq.Eq{"Channels.DeleteAt": int(0)}, sq.Eq{"Users.DeleteAt": int(0)},
sq.Eq{"Users.DeleteAt": int(0)}, sq.Eq{"Channels.Type": []string{"D", "G"}},
sq.Eq{"Channels.Type": []string{"D", "G"}}, }).
}). OrderBy("p.Id").
OrderBy("p.Id"). Limit(uint64(limit))
Limit(uint64(limit))
queryString, args, err := query.ToSql() queryString, args, err := query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
return }
}
var posts []*model.DirectPostForExport var posts []*model.DirectPostForExport
if _, err = s.GetReplica().Select(&posts, queryString, args...); err != nil { if _, err = s.GetReplica().Select(&posts, queryString, args...); err != nil {
result.Err = model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
var channelIds []string var channelIds []string
for _, post := range posts { for _, post := range posts {
channelIds = append(channelIds, post.ChannelId) channelIds = append(channelIds, post.ChannelId)
} }
query = s.getQueryBuilder(). query = s.getQueryBuilder().
Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest"). Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
From("ChannelMembers cm"). From("ChannelMembers cm").
Join("Users u ON ( u.Id = cm.UserId )"). Join("Users u ON ( u.Id = cm.UserId )").
Where(sq.Eq{ Where(sq.Eq{
"cm.ChannelId": channelIds, "cm.ChannelId": channelIds,
}) })
queryString, args, err = query.ToSql() queryString, args, err = query.ToSql()
if err != nil { if err != nil {
result.Err = model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
return }
}
var channelMembers []*model.ChannelMemberForExport var channelMembers []*model.ChannelMemberForExport
if _, err := s.GetReplica().Select(&channelMembers, queryString, args...); err != nil { if _, err := s.GetReplica().Select(&channelMembers, queryString, args...); err != nil {
result.Err = model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPostStore.GetDirectPostParentsForExportAfter", "store.sql_post.get_direct_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
// Build a map of channels and their posts // Build a map of channels and their posts
postsChannelMap := make(map[string][]*model.DirectPostForExport) postsChannelMap := make(map[string][]*model.DirectPostForExport)
for _, post := range posts { for _, post := range posts {
post.ChannelMembers = &[]string{} post.ChannelMembers = &[]string{}
postsChannelMap[post.ChannelId] = append(postsChannelMap[post.ChannelId], post) postsChannelMap[post.ChannelId] = append(postsChannelMap[post.ChannelId], post)
} }
// Build a map of channels and their members // Build a map of channels and their members
channelMembersMap := make(map[string][]string) channelMembersMap := make(map[string][]string)
for _, member := range channelMembers { for _, member := range channelMembers {
channelMembersMap[member.ChannelId] = append(channelMembersMap[member.ChannelId], member.Username) channelMembersMap[member.ChannelId] = append(channelMembersMap[member.ChannelId], member.Username)
} }
// Populate each post ChannelMembers extracting it from the channelMembersMap // Populate each post ChannelMembers extracting it from the channelMembersMap
for channelId := range channelMembersMap { for channelId := range channelMembersMap {
for _, post := range postsChannelMap[channelId] { for _, post := range postsChannelMap[channelId] {
*post.ChannelMembers = channelMembersMap[channelId] *post.ChannelMembers = channelMembersMap[channelId]
}
} }
result.Data = posts }
}) return posts, nil
} }

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

@@ -240,7 +240,7 @@ type PostStore interface {
GetMaxPostSize() int GetMaxPostSize() int
GetParentsForExportAfter(limit int, afterId string) StoreChannel GetParentsForExportAfter(limit int, afterId string) StoreChannel
GetRepliesForExport(parentId string) StoreChannel GetRepliesForExport(parentId string) StoreChannel
GetDirectPostParentsForExportAfter(limit int, afterId string) StoreChannel GetDirectPostParentsForExportAfter(limit int, afterId string) ([]*model.DirectPostForExport, *model.AppError)
} }
type UserStore interface { type UserStore interface {

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

@@ -108,19 +108,28 @@ func (_m *PostStore) Get(id string) (*model.PostList, *model.AppError) {
} }
// GetDirectPostParentsForExportAfter provides a mock function with given fields: limit, afterId // GetDirectPostParentsForExportAfter provides a mock function with given fields: limit, afterId
func (_m *PostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) store.StoreChannel { func (_m *PostStore) GetDirectPostParentsForExportAfter(limit int, afterId string) ([]*model.DirectPostForExport, *model.AppError) {
ret := _m.Called(limit, afterId) ret := _m.Called(limit, afterId)
var r0 store.StoreChannel var r0 []*model.DirectPostForExport
if rf, ok := ret.Get(0).(func(int, string) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(int, string) []*model.DirectPostForExport); ok {
r0 = rf(limit, afterId) r0 = rf(limit, afterId)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).([]*model.DirectPostForExport)
} }
} }
return r0 var r1 *model.AppError
if rf, ok := ret.Get(1).(func(int, string) *model.AppError); ok {
r1 = rf(limit, afterId)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
} }
// GetEtag provides a mock function with given fields: channelId, allowFromCache // GetEtag provides a mock function with given fields: channelId, allowFromCache

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

@@ -2232,11 +2232,10 @@ func testPostStoreGetDirectPostParentsForExportAfter(t *testing.T, ss store.Stor
p1.CreateAt = 1000 p1.CreateAt = 1000
p1 = (<-ss.Post().Save(p1)).Data.(*model.Post) p1 = (<-ss.Post().Save(p1)).Data.(*model.Post)
r1 := <-ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) r1, err := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26))
assert.Nil(t, r1.Err) assert.Nil(t, err)
d1 := r1.Data.([]*model.DirectPostForExport)
assert.Equal(t, p1.Message, d1[0].Message) assert.Equal(t, p1.Message, r1[0].Message)
// Manually truncate Channels table until testlib can handle cleanups // Manually truncate Channels table until testlib can handle cleanups
s.GetMaster().Exec("TRUNCATE Channels") s.GetMaster().Exec("TRUNCATE Channels")
@@ -2292,15 +2291,14 @@ func testPostStoreGetDirectPostParentsForExportAfterDeleted(t *testing.T, ss sto
*o1a = *p1 *o1a = *p1
o1a.DeleteAt = 1 o1a.DeleteAt = 1
o1a.Message = p1.Message + "BBBBBBBBBB" o1a.Message = p1.Message + "BBBBBBBBBB"
if _, err := ss.Post().Update(o1a, p1); err != nil { if _, err = ss.Post().Update(o1a, p1); err != nil {
t.Fatal(err) t.Fatal(err)
} }
r1 := <-ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) r1, err := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26))
assert.Nil(t, r1.Err) assert.Nil(t, err)
d1 := r1.Data.([]*model.DirectPostForExport)
assert.Equal(t, 0, len(d1)) assert.Equal(t, 0, len(r1))
// Manually truncate Channels table until testlib can handle cleanups // Manually truncate Channels table until testlib can handle cleanups
s.GetMaster().Exec("TRUNCATE Channels") s.GetMaster().Exec("TRUNCATE Channels")
@@ -2352,25 +2350,23 @@ func testPostStoreGetDirectPostParentsForExportAfterBatched(t *testing.T, ss sto
sort.Slice(postIds, func(i, j int) bool { return postIds[i] < postIds[j] }) sort.Slice(postIds, func(i, j int) bool { return postIds[i] < postIds[j] })
// Get all posts // Get all posts
r1 := <-ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) r1, err := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26))
assert.Nil(t, r1.Err) assert.Nil(t, err)
d1 := r1.Data.([]*model.DirectPostForExport) assert.Equal(t, len(postIds), len(r1))
assert.Equal(t, len(postIds), len(d1))
var exportedPostIds []string var exportedPostIds []string
for i := range d1 { for i := range r1 {
exportedPostIds = append(exportedPostIds, d1[i].Id) exportedPostIds = append(exportedPostIds, r1[i].Id)
} }
sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] }) sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] })
assert.ElementsMatch(t, postIds, exportedPostIds) assert.ElementsMatch(t, postIds, exportedPostIds)
// Get 100 // Get 100
r1 = <-ss.Post().GetDirectPostParentsForExportAfter(100, strings.Repeat("0", 26)) r1, err = ss.Post().GetDirectPostParentsForExportAfter(100, strings.Repeat("0", 26))
assert.Nil(t, r1.Err) assert.Nil(t, err)
d1 = r1.Data.([]*model.DirectPostForExport) assert.Equal(t, 100, len(r1))
assert.Equal(t, 100, len(d1))
exportedPostIds = []string{} exportedPostIds = []string{}
for i := range d1 { for i := range r1 {
exportedPostIds = append(exportedPostIds, d1[i].Id) exportedPostIds = append(exportedPostIds, r1[i].Id)
} }
sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] }) sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] })
assert.ElementsMatch(t, postIds[:100], exportedPostIds) assert.ElementsMatch(t, postIds[:100], exportedPostIds)