From 70e9647e853cf127d27cf5557d84cbeee403111b Mon Sep 17 00:00:00 2001 From: Martin Kraft Date: Tue, 21 Apr 2020 15:55:30 -0400 Subject: [PATCH] MM-23646: Improve group sync performance. (#14171) Co-authored-by: mattermod --- .gitignore | 1 + store/opentracing_layer.go | 18 ++++++++++++++++++ store/sqlstore/user_store.go | 18 ++++++++++++++++++ store/store.go | 1 + store/storetest/mocks/UserStore.go | 25 +++++++++++++++++++++++++ store/timer_layer.go | 16 ++++++++++++++++ 6 files changed, 79 insertions(+) diff --git a/.gitignore b/.gitignore index 662d932699..19b5c4cd21 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ _testmain.go # Log files *.log *.log.jsonl +*.log.gz # Fuzz binaries and working dir *fuzz.zip diff --git a/store/opentracing_layer.go b/store/opentracing_layer.go index fb29da319a..38f6fcf14c 100644 --- a/store/opentracing_layer.go +++ b/store/opentracing_layer.go @@ -7404,6 +7404,24 @@ func (s *OpenTracingLayerUserStore) GetAllAfter(limit int, afterId string) ([]*m return resultVar0, resultVar1 } +func (s *OpenTracingLayerUserStore) GetAllNotInAuthService(authServices []string) ([]*model.User, *model.AppError) { + origCtx := s.Root.Store.Context() + span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.GetAllNotInAuthService") + s.Root.Store.SetContext(newCtx) + defer func() { + s.Root.Store.SetContext(origCtx) + }() + + defer span.Finish() + resultVar0, resultVar1 := s.UserStore.GetAllNotInAuthService(authServices) + if resultVar1 != nil { + span.LogFields(spanlog.Error(resultVar1)) + ext.Error.Set(span, true) + } + + return resultVar0, resultVar1 +} + func (s *OpenTracingLayerUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.User, *model.AppError) { origCtx := s.Root.Store.Context() span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.GetAllProfiles") diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 3185e55ce6..54dd7ed6f5 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -966,6 +966,24 @@ func (us SqlUserStore) GetAllUsingAuthService(authService string) ([]*model.User return users, nil } +func (us SqlUserStore) GetAllNotInAuthService(authServices []string) ([]*model.User, *model.AppError) { + query := us.usersQuery. + Where(sq.NotEq{"u.AuthService": authServices}). + OrderBy("u.Username ASC") + + queryString, args, err := query.ToSql() + if err != nil { + return nil, model.NewAppError("SqlUserStore.GetAllNotInAuthService", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + var users []*model.User + if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil { + return nil, model.NewAppError("SqlUserStore.GetAllUsingAuthService", "store.sql_user.get_by_auth.other.app_error", nil, "", http.StatusInternalServerError) + } + + return users, nil +} + func (us SqlUserStore) GetByUsername(username string) (*model.User, *model.AppError) { query := us.usersQuery.Where("u.Username = ?", username) diff --git a/store/store.go b/store/store.go index 5ac95bd686..fb71f3df88 100644 --- a/store/store.go +++ b/store/store.go @@ -295,6 +295,7 @@ type UserStore interface { GetByEmail(email string) (*model.User, *model.AppError) GetByAuth(authData *string, authService string) (*model.User, *model.AppError) GetAllUsingAuthService(authService string) ([]*model.User, *model.AppError) + GetAllNotInAuthService(authServices []string) ([]*model.User, *model.AppError) GetByUsername(username string) (*model.User, *model.AppError) GetForLogin(loginId string, allowSignInWithUsername, allowSignInWithEmail bool) (*model.User, *model.AppError) VerifyEmail(userId, email string) (string, *model.AppError) diff --git a/store/storetest/mocks/UserStore.go b/store/storetest/mocks/UserStore.go index 886f1d869f..8f41f19506 100644 --- a/store/storetest/mocks/UserStore.go +++ b/store/storetest/mocks/UserStore.go @@ -292,6 +292,31 @@ func (_m *UserStore) GetAllAfter(limit int, afterId string) ([]*model.User, *mod return r0, r1 } +// GetAllNotInAuthService provides a mock function with given fields: authServices +func (_m *UserStore) GetAllNotInAuthService(authServices []string) ([]*model.User, *model.AppError) { + ret := _m.Called(authServices) + + var r0 []*model.User + if rf, ok := ret.Get(0).(func([]string) []*model.User); ok { + r0 = rf(authServices) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func([]string) *model.AppError); ok { + r1 = rf(authServices) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + // GetAllProfiles provides a mock function with given fields: options func (_m *UserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.User, *model.AppError) { ret := _m.Called(options) diff --git a/store/timer_layer.go b/store/timer_layer.go index 6677508d43..7682f0f610 100644 --- a/store/timer_layer.go +++ b/store/timer_layer.go @@ -6695,6 +6695,22 @@ func (s *TimerLayerUserStore) GetAllAfter(limit int, afterId string) ([]*model.U return resultVar0, resultVar1 } +func (s *TimerLayerUserStore) GetAllNotInAuthService(authServices []string) ([]*model.User, *model.AppError) { + start := timemodule.Now() + + resultVar0, resultVar1 := s.UserStore.GetAllNotInAuthService(authServices) + + elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second) + if s.Root.Metrics != nil { + success := "false" + if resultVar1 == nil { + success = "true" + } + s.Root.Metrics.ObserveStoreMethodDuration("UserStore.GetAllNotInAuthService", success, elapsed) + } + return resultVar0, resultVar1 +} + func (s *TimerLayerUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.User, *model.AppError) { start := timemodule.Now()