From f97e6368c8ef5828a061f372c9209da71238aaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Villablanca=20V=C3=A1squez?= Date: Mon, 17 Jun 2019 14:32:37 -0400 Subject: [PATCH] Migrates Channel.AutocompleteInTeam, Channel.SearchInTeam and Channel.SearchMore to sync by default (#11229) --- app/channel.go | 18 +-- store/sqlstore/channel_store.go | 174 ++++++++++++-------------- store/store.go | 6 +- store/storetest/channel_store.go | 80 ++++++------ store/storetest/mocks/ChannelStore.go | 57 ++++++--- 5 files changed, 169 insertions(+), 166 deletions(-) diff --git a/app/channel.go b/app/channel.go index ce5414300f..d69b6da10a 100644 --- a/app/channel.go +++ b/app/channel.go @@ -1774,11 +1774,7 @@ func (a *App) AutocompleteChannels(teamId string, term string) (*model.ChannelLi return &channelList, nil } - result := <-a.Srv.Store.Channel().AutocompleteInTeam(teamId, term, includeDeleted) - if result.Err != nil { - return nil, result.Err - } - return result.Data.(*model.ChannelList), nil + return a.Srv.Store.Channel().AutocompleteInTeam(teamId, term, includeDeleted) } func (a *App) AutocompleteChannelsForSearch(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { @@ -1818,20 +1814,12 @@ func (a *App) SearchChannels(teamId string, term string) (*model.ChannelList, *m term = strings.TrimSpace(term) - result := <-a.Srv.Store.Channel().SearchInTeam(teamId, term, includeDeleted) - if result.Err != nil { - return nil, result.Err - } - return result.Data.(*model.ChannelList), nil + return a.Srv.Store.Channel().SearchInTeam(teamId, term, includeDeleted) } func (a *App) SearchChannelsUserNotIn(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { term = strings.TrimSpace(term) - result := <-a.Srv.Store.Channel().SearchMore(userId, teamId, term) - if result.Err != nil { - return nil, result.Err - } - return result.Data.(*model.ChannelList), nil + return a.Srv.Store.Channel().SearchMore(userId, teamId, term) } func (a *App) MarkChannelsAsViewed(channelIds []string, userId string, currentSessionId string) (map[string]int64, *model.AppError) { diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index 9c73d954c7..ea9c0ec724 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -1957,50 +1957,48 @@ func (s SqlChannelStore) GetMembersForUserWithPagination(teamId, userId string, }) } -func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - deleteFilter := "AND c.DeleteAt = 0" - if includeDeleted { - deleteFilter = "" +func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) { + deleteFilter := "AND c.DeleteAt = 0" + if includeDeleted { + deleteFilter = "" + } + + queryFormat := ` + SELECT + Channels.* + FROM + Channels + JOIN + PublicChannels c ON (c.Id = Channels.Id) + WHERE + c.TeamId = :TeamId + ` + deleteFilter + ` + %v + LIMIT ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT) + + var channels model.ChannelList + + if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" { + if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil { + return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) } + } else { + // Using a UNION results in index_merge and fulltext queries and is much faster than the ref + // query you would get using an OR of the LIKE and full-text clauses. + fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose") + likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause) + fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause) + query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery) - queryFormat := ` - SELECT - Channels.* - FROM - Channels - JOIN - PublicChannels c ON (c.Id = Channels.Id) - WHERE - c.TeamId = :TeamId - ` + deleteFilter + ` - %v - LIMIT ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT) - - var channels model.ChannelList - - if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" { - if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil { - result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) - } - } else { - // Using a UNION results in index_merge and fulltext queries and is much faster than the ref - // query you would get using an OR of the LIKE and full-text clauses. - fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose") - likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause) - fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause) - query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery) - - if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil { - result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) - } + if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil { + return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) } + } - sort.Slice(channels, func(a, b int) bool { - return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName) - }) - result.Data = &channels + sort.Slice(channels, func(a, b int) bool { + return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName) }) + return &channels, nil } func (s SqlChannelStore) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) store.StoreChannel { @@ -2100,29 +2098,27 @@ func (s SqlChannelStore) autocompleteInTeamForSearchDirectMessages(userId string return channels, nil } -func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - deleteFilter := "AND c.DeleteAt = 0" - if includeDeleted { - deleteFilter = "" - } +func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) { + deleteFilter := "AND c.DeleteAt = 0" + if includeDeleted { + deleteFilter = "" + } - *result = s.performSearch(` - SELECT - Channels.* - FROM - Channels - JOIN - PublicChannels c ON (c.Id = Channels.Id) - WHERE - c.TeamId = :TeamId - `+deleteFilter+` - SEARCH_CLAUSE - ORDER BY c.DisplayName - LIMIT 100 + return s.performSearch(` + SELECT + Channels.* + FROM + Channels + JOIN + PublicChannels c ON (c.Id = Channels.Id) + WHERE + c.TeamId = :TeamId + `+deleteFilter+` + SEARCH_CLAUSE + ORDER BY c.DisplayName + LIMIT 100 `, term, map[string]interface{}{ - "TeamId": teamId, - }) + "TeamId": teamId, }) } @@ -2172,37 +2168,35 @@ func (s SqlChannelStore) SearchAllChannels(term string, opts store.ChannelSearch }) } -func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - *result = s.performSearch(` +func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) { + return s.performSearch(` + SELECT + Channels.* + FROM + Channels + JOIN + PublicChannels c ON (c.Id = Channels.Id) + WHERE + c.TeamId = :TeamId + AND c.DeleteAt = 0 + AND c.Id NOT IN ( SELECT - Channels.* + c.Id FROM - Channels + PublicChannels c JOIN - PublicChannels c ON (c.Id = Channels.Id) + ChannelMembers cm ON (cm.ChannelId = c.Id) WHERE - c.TeamId = :TeamId + c.TeamId = :TeamId + AND cm.UserId = :UserId AND c.DeleteAt = 0 - AND c.Id NOT IN ( - SELECT - c.Id - FROM - PublicChannels c - JOIN - ChannelMembers cm ON (cm.ChannelId = c.Id) - WHERE - c.TeamId = :TeamId - AND cm.UserId = :UserId - AND c.DeleteAt = 0 - ) - SEARCH_CLAUSE - ORDER BY c.DisplayName - LIMIT 100 + ) + SEARCH_CLAUSE + ORDER BY c.DisplayName + LIMIT 100 `, term, map[string]interface{}{ - "TeamId": teamId, - "UserId": userId, - }) + "TeamId": teamId, + "UserId": userId, }) } @@ -2277,9 +2271,7 @@ func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string) return } -func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult { - result := store.StoreResult{} - +func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) (*model.ChannelList, *model.AppError) { likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose") if likeTerm == "" { // If the likeTerm is empty after preparing, then don't bother searching. @@ -2294,12 +2286,10 @@ func (s SqlChannelStore) performSearch(searchQuery string, term string, paramete var channels model.ChannelList if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil { - result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) - return result + return nil, model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) } - result.Data = &channels - return result + return &channels, nil } func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) store.StoreChannel { diff --git a/store/store.go b/store/store.go index 176657ca87..2226fa80f5 100644 --- a/store/store.go +++ b/store/store.go @@ -180,11 +180,11 @@ type ChannelStore interface { AnalyticsTypeCount(teamId string, channelType string) (int64, *model.AppError) GetMembersForUser(teamId string, userId string) StoreChannel GetMembersForUserWithPagination(teamId, userId string, page, perPage int) StoreChannel - AutocompleteInTeam(teamId string, term string, includeDeleted bool) StoreChannel + AutocompleteInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) StoreChannel SearchAllChannels(term string, opts ChannelSearchOpts) StoreChannel - SearchInTeam(teamId string, term string, includeDeleted bool) StoreChannel - SearchMore(userId string, teamId string, term string) StoreChannel + SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) + SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) GetMembersByIds(channelId string, userIds []string) StoreChannel AnalyticsDeletedTypeCount(teamId string, channelType string) StoreChannel GetChannelUnread(channelId, userId string) (*model.ChannelUnread, *model.AppError) diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index e720018962..d7d88e1e1b 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -2108,33 +2108,33 @@ func testChannelStoreSearchMore(t *testing.T, ss store.Store) { require.Nil(t, err, "channel should have been deleted") t.Run("three public channels matching 'ChannelA', but already a member of one and one deleted", func(t *testing.T) { - result := <-ss.Channel().SearchMore(m1.UserId, teamId, "ChannelA") - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o3}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchMore(m1.UserId, teamId, "ChannelA") + require.Nil(t, err) + require.Equal(t, &model.ChannelList{&o3}, channels) }) t.Run("one public channels, but already a member", func(t *testing.T) { - result := <-ss.Channel().SearchMore(m1.UserId, teamId, o4.Name) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchMore(m1.UserId, teamId, o4.Name) + require.Nil(t, err) + require.Equal(t, &model.ChannelList{}, channels) }) t.Run("three matching channels, but only two public", func(t *testing.T) { - result := <-ss.Channel().SearchMore(m1.UserId, teamId, "off-") - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o7, &o6}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchMore(m1.UserId, teamId, "off-") + require.Nil(t, err) + require.Equal(t, &model.ChannelList{&o7, &o6}, channels) }) t.Run("one channel matching 'off-topic'", func(t *testing.T) { - result := <-ss.Channel().SearchMore(m1.UserId, teamId, "off-topic") - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o6}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchMore(m1.UserId, teamId, "off-topic") + require.Nil(t, err) + require.Equal(t, &model.ChannelList{&o6}, channels) }) t.Run("search purpose", func(t *testing.T) { - result := <-ss.Channel().SearchMore(m1.UserId, teamId, "now searchable") - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o9}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchMore(m1.UserId, teamId, "now searchable") + require.Nil(t, err) + require.Equal(t, &model.ChannelList{&o9}, channels) }) } @@ -2320,16 +2320,14 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { {"pipe ignored", teamId, "town square |", false, &model.ChannelList{&o9}}, } - for name, search := range map[string]func(teamId string, term string, includeDeleted bool) store.StoreChannel{ + for name, search := range map[string]func(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError){ "AutocompleteInTeam": ss.Channel().AutocompleteInTeam, "SearchInTeam": ss.Channel().SearchInTeam, } { for _, testCase := range testCases { t.Run(testCase.Description, func(t *testing.T) { - result := <-search(testCase.TeamId, testCase.Term, testCase.IncludeDeleted) - require.Nil(t, result.Err) - - channels := result.Data.(*model.ChannelList) + channels, err := search(testCase.TeamId, testCase.Term, testCase.IncludeDeleted) + require.Nil(t, err) // AutoCompleteInTeam doesn't currently sort its output results. if name == "AutocompleteInTeam" { @@ -3150,9 +3148,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, err) t.Run("o1 and o2 initially listed in public channels", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o1, &o2}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{&o1, &o2}, channels) }) o1.DeleteAt = model.GetMillis() @@ -3162,17 +3160,17 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, e, "channel should have been deleted") t.Run("o1 still listed in public channels when marked as deleted", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o1, &o2}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{&o1, &o2}, channels) }) <-ss.Channel().PermanentDelete(o1.Id) t.Run("o1 no longer listed in public channels when permanently deleted", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o2}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{&o2}, channels) }) o2.Type = model.CHANNEL_PRIVATE @@ -3180,9 +3178,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, appErr) t.Run("o2 no longer listed since now private", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{}, channels) }) o2.Type = model.CHANNEL_OPEN @@ -3190,9 +3188,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, appErr) t.Run("o2 listed once again since now public", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o2}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{&o2}, channels) }) // o3 is a public channel on the team that already existed in the PublicChannels table. @@ -3246,9 +3244,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, execerr) t.Run("verify o3 INSERT converted to UPDATE", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o2, &o3}, result.Data.(*model.ChannelList)) + channels, channelErr := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, channelErr) + require.Equal(t, &model.ChannelList{&o2, &o3}, channels) }) // o4 is a public channel on the team that existed in the Channels table but was omitted from the PublicChannels table. @@ -3277,9 +3275,9 @@ func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) require.Nil(t, appErr) t.Run("verify o4 UPDATE converted to INSERT", func(t *testing.T) { - result := <-ss.Channel().SearchInTeam(teamId, "", true) - require.Nil(t, result.Err) - require.Equal(t, &model.ChannelList{&o2, &o3, &o4}, result.Data.(*model.ChannelList)) + channels, err := ss.Channel().SearchInTeam(teamId, "", true) + require.Nil(t, err) + require.Equal(t, &model.ChannelList{&o2, &o3, &o4}, channels) }) } diff --git a/store/storetest/mocks/ChannelStore.go b/store/storetest/mocks/ChannelStore.go index 8f64454673..2668fffec5 100644 --- a/store/storetest/mocks/ChannelStore.go +++ b/store/storetest/mocks/ChannelStore.go @@ -53,19 +53,28 @@ func (_m *ChannelStore) AnalyticsTypeCount(teamId string, channelType string) (i } // AutocompleteInTeam provides a mock function with given fields: teamId, term, includeDeleted -func (_m *ChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { +func (_m *ChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) { ret := _m.Called(teamId, term, includeDeleted) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string, bool) store.StoreChannel); ok { + var r0 *model.ChannelList + if rf, ok := ret.Get(0).(func(string, string, bool) *model.ChannelList); ok { r0 = rf(teamId, term, includeDeleted) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.ChannelList) } } - return r0 + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string, bool) *model.AppError); ok { + r1 = rf(teamId, term, includeDeleted) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 } // AutocompleteInTeamForSearch provides a mock function with given fields: teamId, userId, term, includeDeleted @@ -1072,35 +1081,53 @@ func (_m *ChannelStore) SearchAllChannels(term string, opts store.ChannelSearchO } // SearchInTeam provides a mock function with given fields: teamId, term, includeDeleted -func (_m *ChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { +func (_m *ChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) { ret := _m.Called(teamId, term, includeDeleted) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string, bool) store.StoreChannel); ok { + var r0 *model.ChannelList + if rf, ok := ret.Get(0).(func(string, string, bool) *model.ChannelList); ok { r0 = rf(teamId, term, includeDeleted) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.ChannelList) } } - return r0 + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string, bool) *model.AppError); ok { + r1 = rf(teamId, term, includeDeleted) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 } // SearchMore provides a mock function with given fields: userId, teamId, term -func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel { +func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) { ret := _m.Called(userId, teamId, term) - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string, string) store.StoreChannel); ok { + var r0 *model.ChannelList + if rf, ok := ret.Get(0).(func(string, string, string) *model.ChannelList); ok { r0 = rf(userId, teamId, term) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) + r0 = ret.Get(0).(*model.ChannelList) } } - return r0 + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string, string) *model.AppError); ok { + r1 = rf(userId, teamId, term) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 } // SetDeleteAt provides a mock function with given fields: channelId, deleteAt, updateAt