From ae6e864f57bdbbfeb7f413e68f8664d58401ad9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Ga=C4=87e=C5=A1a?= Date: Thu, 29 Dec 2022 11:52:50 +0100 Subject: [PATCH] Removed sync store for token/service/user/service-acc (#139) --- internal/store/database/service.go | 48 ++++++----- internal/store/database/service_account.go | 49 ++++++----- .../store/database/service_account_sync.go | 79 ------------------ internal/store/database/service_sync.go | 76 ----------------- internal/store/database/store_test.go | 45 ++++++----- internal/store/database/token.go | 34 ++++++-- internal/store/database/token_sync.go | 77 ------------------ internal/store/database/user.go | 58 +++++++------ internal/store/database/user_sync.go | 81 ------------------- internal/store/database/user_test.go | 6 +- internal/store/database/wire.go | 36 +-------- 11 files changed, 151 insertions(+), 438 deletions(-) delete mode 100644 internal/store/database/service_account_sync.go delete mode 100644 internal/store/database/service_sync.go delete mode 100644 internal/store/database/token_sync.go delete mode 100644 internal/store/database/user_sync.go diff --git a/internal/store/database/service.go b/internal/store/database/service.go index 36fbf5dd8..996da6043 100644 --- a/internal/store/database/service.go +++ b/internal/store/database/service.go @@ -6,10 +6,10 @@ package database import ( "context" - "database/sql" "fmt" "github.com/harness/gitness/internal/store" + "github.com/harness/gitness/internal/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -43,10 +43,13 @@ type ServiceStore struct { // Find finds the service by id. func (s *ServiceStore) Find(ctx context.Context, id int64) (*types.Service, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(service) - if err := s.db.GetContext(ctx, dst, serviceSelectID, id); err != nil { + if err := db.GetContext(ctx, dst, serviceSelectID, id); err != nil { return nil, processSQLErrorf(err, "Select by id query failed") } + return s.mapDBService(dst), nil } @@ -60,10 +63,13 @@ func (s *ServiceStore) FindUID(ctx context.Context, uid string) (*types.Service, return nil, store.ErrResourceNotFound } + db := dbtx.GetAccessor(ctx, s.db) + dst := new(service) - if err = s.db.GetContext(ctx, dst, serviceSelectUIDUnique, uidUnique); err != nil { + if err = db.GetContext(ctx, dst, serviceSelectUIDUnique, uidUnique); err != nil { return nil, processSQLErrorf(err, "Select by uid query failed") } + return s.mapDBService(dst), nil } @@ -74,12 +80,14 @@ func (s *ServiceStore) Create(ctx context.Context, svc *types.Service) error { return fmt.Errorf("failed to map db service: %w", err) } - query, arg, err := s.db.BindNamed(serviceInsert, dbSVC) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(serviceInsert, dbSVC) if err != nil { return processSQLErrorf(err, "Failed to bind service object") } - if err = s.db.QueryRowContext(ctx, query, arg...).Scan(&svc.ID); err != nil { + if err = db.QueryRowContext(ctx, query, arg...).Scan(&svc.ID); err != nil { return processSQLErrorf(err, "Insert query failed") } @@ -93,12 +101,14 @@ func (s *ServiceStore) Update(ctx context.Context, svc *types.Service) error { return fmt.Errorf("failed to map db service: %w", err) } - query, arg, err := s.db.BindNamed(serviceUpdate, dbSVC) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(serviceUpdate, dbSVC) if err != nil { return processSQLErrorf(err, "Failed to bind service object") } - if _, err = s.db.ExecContext(ctx, query, arg...); err != nil { + if _, err = db.ExecContext(ctx, query, arg...); err != nil { return processSQLErrorf(err, "Update query failed") } @@ -107,38 +117,40 @@ func (s *ServiceStore) Update(ctx context.Context, svc *types.Service) error { // Delete deletes the service. func (s *ServiceStore) Delete(ctx context.Context, id int64) error { - tx, err := s.db.BeginTx(ctx, nil) - if err != nil { - return processSQLErrorf(err, "Failed to start a new transaction") - } - defer func(tx *sql.Tx) { - _ = tx.Rollback() - }(tx) + db := dbtx.GetAccessor(ctx, s.db) + // delete the service - if _, err = tx.ExecContext(ctx, serviceDelete, id); err != nil { + if _, err := db.ExecContext(ctx, serviceDelete, id); err != nil { return processSQLErrorf(err, "The delete query failed") } - return tx.Commit() + + return nil } // List returns a list of service for a specific parent. func (s *ServiceStore) List(ctx context.Context) ([]*types.Service, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := []*service{} - err := s.db.SelectContext(ctx, &dst, serviceSelect) + err := db.SelectContext(ctx, &dst, serviceSelect) if err != nil { return nil, processSQLErrorf(err, "Failed executing default list query") } + return s.mapDBServices(dst), nil } // Count returns a count of service for a specific parent. func (s *ServiceStore) Count(ctx context.Context) (int64, error) { + db := dbtx.GetAccessor(ctx, s.db) + var count int64 - err := s.db.QueryRowContext(ctx, serviceCount).Scan(&count) + err := db.QueryRowContext(ctx, serviceCount).Scan(&count) if err != nil { return 0, processSQLErrorf(err, "Failed executing count query") } + return count, nil } diff --git a/internal/store/database/service_account.go b/internal/store/database/service_account.go index 9c7be9d83..07faa4a47 100644 --- a/internal/store/database/service_account.go +++ b/internal/store/database/service_account.go @@ -6,10 +6,10 @@ package database import ( "context" - "database/sql" "fmt" "github.com/harness/gitness/internal/store" + "github.com/harness/gitness/internal/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -43,8 +43,10 @@ type ServiceAccountStore struct { // Find finds the service account by id. func (s *ServiceAccountStore) Find(ctx context.Context, id int64) (*types.ServiceAccount, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(serviceAccount) - if err := s.db.GetContext(ctx, dst, serviceAccountSelectID, id); err != nil { + if err := db.GetContext(ctx, dst, serviceAccountSelectID, id); err != nil { return nil, processSQLErrorf(err, "Select by id query failed") } return s.mapDBServiceAccount(dst), nil @@ -60,10 +62,13 @@ func (s *ServiceAccountStore) FindUID(ctx context.Context, uid string) (*types.S return nil, store.ErrResourceNotFound } + db := dbtx.GetAccessor(ctx, s.db) + dst := new(serviceAccount) - if err = s.db.GetContext(ctx, dst, serviceAccountSelectUIDUnique, uidUnique); err != nil { + if err = db.GetContext(ctx, dst, serviceAccountSelectUIDUnique, uidUnique); err != nil { return nil, processSQLErrorf(err, "Select by uid query failed") } + return s.mapDBServiceAccount(dst), nil } @@ -74,12 +79,14 @@ func (s *ServiceAccountStore) Create(ctx context.Context, sa *types.ServiceAccou return fmt.Errorf("failed to map db service account: %w", err) } - query, arg, err := s.db.BindNamed(serviceAccountInsert, dbSA) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(serviceAccountInsert, dbSA) if err != nil { return processSQLErrorf(err, "Failed to bind service account object") } - if err = s.db.QueryRowContext(ctx, query, arg...).Scan(&sa.ID); err != nil { + if err = db.QueryRowContext(ctx, query, arg...).Scan(&sa.ID); err != nil { return processSQLErrorf(err, "Insert query failed") } @@ -93,12 +100,14 @@ func (s *ServiceAccountStore) Update(ctx context.Context, sa *types.ServiceAccou return fmt.Errorf("failed to map db service account: %w", err) } - query, arg, err := s.db.BindNamed(serviceAccountUpdate, dbSA) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(serviceAccountUpdate, dbSA) if err != nil { return processSQLErrorf(err, "Failed to bind service account object") } - if _, err = s.db.ExecContext(ctx, query, arg...); err != nil { + if _, err = db.ExecContext(ctx, query, arg...); err != nil { return processSQLErrorf(err, "Update query failed") } @@ -107,40 +116,40 @@ func (s *ServiceAccountStore) Update(ctx context.Context, sa *types.ServiceAccou // Delete deletes the service account. func (s *ServiceAccountStore) Delete(ctx context.Context, id int64) error { - tx, err := s.db.BeginTx(ctx, nil) - if err != nil { - return processSQLErrorf(err, "Failed to start a new transaction") - } - defer func(tx *sql.Tx) { - _ = tx.Rollback() - }(tx) - // delete the service account - if _, err = tx.ExecContext(ctx, serviceAccountDelete, id); err != nil { + db := dbtx.GetAccessor(ctx, s.db) + + if _, err := db.ExecContext(ctx, serviceAccountDelete, id); err != nil { return processSQLErrorf(err, "The delete query failed") } - return tx.Commit() + + return nil } // List returns a list of service accounts for a specific parent. func (s *ServiceAccountStore) List(ctx context.Context, parentType enum.ParentResourceType, parentID int64) ([]*types.ServiceAccount, error) { - dst := []*serviceAccount{} + db := dbtx.GetAccessor(ctx, s.db) - err := s.db.SelectContext(ctx, &dst, serviceAccountSelectByParentTypeAndID, parentType, parentID) + dst := []*serviceAccount{} + err := db.SelectContext(ctx, &dst, serviceAccountSelectByParentTypeAndID, parentType, parentID) if err != nil { return nil, processSQLErrorf(err, "Failed executing default list query") } + return s.mapDBServiceAccounts(dst), nil } // Count returns a count of service accounts for a specific parent. func (s *ServiceAccountStore) Count(ctx context.Context, parentType enum.ParentResourceType, parentID int64) (int64, error) { + db := dbtx.GetAccessor(ctx, s.db) + var count int64 - err := s.db.QueryRowContext(ctx, serviceAccountCountByParentTypeAndID, parentType, parentID).Scan(&count) + err := db.QueryRowContext(ctx, serviceAccountCountByParentTypeAndID, parentType, parentID).Scan(&count) if err != nil { return 0, processSQLErrorf(err, "Failed executing count query") } + return count, nil } diff --git a/internal/store/database/service_account_sync.go b/internal/store/database/service_account_sync.go deleted file mode 100644 index 1c3048b4c..000000000 --- a/internal/store/database/service_account_sync.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2022 Harness Inc. All rights reserved. -// Use of this source code is governed by the Polyform Free Trial License -// that can be found in the LICENSE.md file for this repository. - -package database - -import ( - "context" - - "github.com/harness/gitness/internal/store" - "github.com/harness/gitness/internal/store/database/mutex" - "github.com/harness/gitness/types" - "github.com/harness/gitness/types/enum" -) - -var _ store.ServiceAccountStore = (*ServiceAccountStoreSync)(nil) - -// NewServiceAccountStoreSync returns a new ServiceAccountStoreSync. -func NewServiceAccountStoreSync(base *ServiceAccountStore) *ServiceAccountStoreSync { - return &ServiceAccountStoreSync{base} -} - -// ServiceAccountStoreSync synchronizes read and write access to the -// service account store. This prevents race conditions when the database -// type is sqlite3. -type ServiceAccountStoreSync struct { - base *ServiceAccountStore -} - -// Find finds the service account by id. -func (s *ServiceAccountStoreSync) Find(ctx context.Context, id int64) (*types.ServiceAccount, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Find(ctx, id) -} - -// FindUID finds the service account by uid. -func (s *ServiceAccountStoreSync) FindUID(ctx context.Context, uid string) (*types.ServiceAccount, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.FindUID(ctx, uid) -} - -// Create saves the service account. -func (s *ServiceAccountStoreSync) Create(ctx context.Context, sa *types.ServiceAccount) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Create(ctx, sa) -} - -// Update updates the service account details. -func (s *ServiceAccountStoreSync) Update(ctx context.Context, sa *types.ServiceAccount) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Update(ctx, sa) -} - -// Delete deletes the service account. -func (s *ServiceAccountStoreSync) Delete(ctx context.Context, id int64) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Delete(ctx, id) -} - -// List returns a list of service accounts for a specific parent. -func (s *ServiceAccountStoreSync) List(ctx context.Context, parentType enum.ParentResourceType, - parentID int64) ([]*types.ServiceAccount, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.List(ctx, parentType, parentID) -} - -// Count returns a count of service accounts for a specific parent. -func (s *ServiceAccountStoreSync) Count(ctx context.Context, parentType enum.ParentResourceType, - parentID int64) (int64, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Count(ctx, parentType, parentID) -} diff --git a/internal/store/database/service_sync.go b/internal/store/database/service_sync.go deleted file mode 100644 index 9df3b7737..000000000 --- a/internal/store/database/service_sync.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2022 Harness Inc. All rights reserved. -// Use of this source code is governed by the Polyform Free Trial License -// that can be found in the LICENSE.md file for this repository. - -package database - -import ( - "context" - - "github.com/harness/gitness/internal/store" - "github.com/harness/gitness/internal/store/database/mutex" - "github.com/harness/gitness/types" -) - -var _ store.ServiceStore = (*ServiceStoreSync)(nil) - -// NewServiceStoreSync returns a new ServiceStoreSync. -func NewServiceStoreSync(base *ServiceStore) *ServiceStoreSync { - return &ServiceStoreSync{base} -} - -// ServiceStoreSync synchronizes read and write access to the -// service store. This prevents race conditions when the database -// type is sqlite3. -type ServiceStoreSync struct { - base *ServiceStore -} - -// Find finds the service by id. -func (s *ServiceStoreSync) Find(ctx context.Context, id int64) (*types.Service, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Find(ctx, id) -} - -// FindUID finds the service by uid. -func (s *ServiceStoreSync) FindUID(ctx context.Context, uid string) (*types.Service, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.FindUID(ctx, uid) -} - -// Create saves the service. -func (s *ServiceStoreSync) Create(ctx context.Context, sa *types.Service) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Create(ctx, sa) -} - -// Update updates the service. -func (s *ServiceStoreSync) Update(ctx context.Context, sa *types.Service) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Update(ctx, sa) -} - -// Delete deletes the service. -func (s *ServiceStoreSync) Delete(ctx context.Context, id int64) error { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Delete(ctx, id) -} - -// List returns a list of service for a specific parent. -func (s *ServiceStoreSync) List(ctx context.Context) ([]*types.Service, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.List(ctx) -} - -// Count returns a count of service for a specific parent. -func (s *ServiceStoreSync) Count(ctx context.Context) (int64, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Count(ctx) -} diff --git a/internal/store/database/store_test.go b/internal/store/database/store_test.go index 0f27b4e5a..e809aa116 100644 --- a/internal/store/database/store_test.go +++ b/internal/store/database/store_test.go @@ -30,28 +30,31 @@ func connect() (*sqlx.DB, error) { // seed seed the database state. func seed(db *sqlx.DB) error { - _, err := db.Exec("DELETE FROM executions") - if err != nil { + /* + _, err := db.Exec("DELETE FROM executions") + if err != nil { + return err + } + _, err = db.Exec("DELETE FROM pipelines") + if err != nil { + return err + } + _, err = db.Exec("DELETE FROM users") + if err != nil { + return err + } + _, err = db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1") + if err != nil { + return err + } + _, err = db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1") + if err != nil { + return err + } + _, err = db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1") return err - } - _, err = db.Exec("DELETE FROM pipelines") - if err != nil { - return err - } - _, err = db.Exec("DELETE FROM users") - if err != nil { - return err - } - _, err = db.Exec("ALTER SEQUENCE users_user_id_seq RESTART WITH 1") - if err != nil { - return err - } - _, err = db.Exec("ALTER SEQUENCE pipelines_pipeline_id_seq RESTART WITH 1") - if err != nil { - return err - } - _, err = db.Exec("ALTER SEQUENCE executions_execution_id_seq RESTART WITH 1") - return err + */ + return nil } // unmarshal a testdata file. diff --git a/internal/store/database/token.go b/internal/store/database/token.go index 3a7b458e0..2228fc742 100644 --- a/internal/store/database/token.go +++ b/internal/store/database/token.go @@ -8,6 +8,7 @@ import ( "context" "github.com/harness/gitness/internal/store" + "github.com/harness/gitness/internal/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -28,30 +29,38 @@ type TokenStore struct { // Find finds the token by id. func (s *TokenStore) Find(ctx context.Context, id int64) (*types.Token, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(types.Token) - if err := s.db.GetContext(ctx, dst, TokenSelectByID, id); err != nil { + if err := db.GetContext(ctx, dst, TokenSelectByID, id); err != nil { return nil, processSQLErrorf(err, "Select query failed") } + return dst, nil } // Find finds the token by principalId and tokenUID. func (s *TokenStore) FindByUID(ctx context.Context, principalID int64, tokenUID string) (*types.Token, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(types.Token) - if err := s.db.GetContext(ctx, dst, TokenSelectByPrincipalIDAndUID, principalID, tokenUID); err != nil { + if err := db.GetContext(ctx, dst, TokenSelectByPrincipalIDAndUID, principalID, tokenUID); err != nil { return nil, processSQLErrorf(err, "Select query failed") } + return dst, nil } // Create saves the token details. func (s *TokenStore) Create(ctx context.Context, token *types.Token) error { - query, arg, err := s.db.BindNamed(tokenInsert, token) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(tokenInsert, token) if err != nil { return processSQLErrorf(err, "Failed to bind token object") } - if err = s.db.QueryRowContext(ctx, query, arg...).Scan(&token.ID); err != nil { + if err = db.QueryRowContext(ctx, query, arg...).Scan(&token.ID); err != nil { return processSQLErrorf(err, "Insert query failed") } @@ -60,7 +69,9 @@ func (s *TokenStore) Create(ctx context.Context, token *types.Token) error { // Delete deletes the token with the given id. func (s *TokenStore) Delete(ctx context.Context, id int64) error { - if _, err := s.db.ExecContext(ctx, tokenDelete, id); err != nil { + db := dbtx.GetAccessor(ctx, s.db) + + if _, err := db.ExecContext(ctx, tokenDelete, id); err != nil { return processSQLErrorf(err, "The delete query failed") } @@ -69,7 +80,9 @@ func (s *TokenStore) Delete(ctx context.Context, id int64) error { // DeleteForPrincipal deletes all tokens for a specific principal. func (s *TokenStore) DeleteForPrincipal(ctx context.Context, principalID int64) error { - if _, err := s.db.ExecContext(ctx, tokenDeleteForPrincipal, principalID); err != nil { + db := dbtx.GetAccessor(ctx, s.db) + + if _, err := db.ExecContext(ctx, tokenDeleteForPrincipal, principalID); err != nil { return processSQLErrorf(err, "The delete query failed") } @@ -79,22 +92,27 @@ func (s *TokenStore) DeleteForPrincipal(ctx context.Context, principalID int64) // Count returns a count of tokens of a specifc type for a specific principal. func (s *TokenStore) Count(ctx context.Context, principalID int64, tokenType enum.TokenType) (int64, error) { + db := dbtx.GetAccessor(ctx, s.db) + var count int64 - err := s.db.QueryRowContext(ctx, tokenCountForPrincipalIDOfType, principalID, tokenType).Scan(&count) + err := db.QueryRowContext(ctx, tokenCountForPrincipalIDOfType, principalID, tokenType).Scan(&count) if err != nil { return 0, processSQLErrorf(err, "Failed executing count query") } + return count, nil } // List returns a list of tokens of a specific type for a specific principal. func (s *TokenStore) List(ctx context.Context, principalID int64, tokenType enum.TokenType) ([]*types.Token, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := []*types.Token{} // TODO: custom filters / sorting for tokens. - err := s.db.SelectContext(ctx, &dst, tokenSelectForPrincipalIDOfType, principalID, tokenType) + err := db.SelectContext(ctx, &dst, tokenSelectForPrincipalIDOfType, principalID, tokenType) if err != nil { return nil, processSQLErrorf(err, "Failed executing token list query") } diff --git a/internal/store/database/token_sync.go b/internal/store/database/token_sync.go deleted file mode 100644 index 3676f43c7..000000000 --- a/internal/store/database/token_sync.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2022 Harness Inc. All rights reserved. -// Use of this source code is governed by the Polyform Free Trial License -// that can be found in the LICENSE.md file for this repository. - -package database - -import ( - "context" - - "github.com/harness/gitness/internal/store" - "github.com/harness/gitness/internal/store/database/mutex" - "github.com/harness/gitness/types" - "github.com/harness/gitness/types/enum" -) - -var _ store.TokenStore = (*TokenStoreSync)(nil) - -// NewTokenStoreSync returns a new TokenStoreSync. -func NewTokenStoreSync(store *TokenStore) *TokenStoreSync { - return &TokenStoreSync{base: store} -} - -// TokenStoreSync synronizes read and write access to the -// token store. This prevents race conditions when the database -// type is sqlite3. -type TokenStoreSync struct{ base *TokenStore } - -// Find finds the token by id. -func (s *TokenStoreSync) Find(ctx context.Context, id int64) (*types.Token, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Find(ctx, id) -} - -// Find finds the token by principalId and tokenUID. -func (s *TokenStoreSync) FindByUID(ctx context.Context, principalID int64, tokenUID string) (*types.Token, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.FindByUID(ctx, principalID, tokenUID) -} - -// Create saves the token details. -func (s *TokenStoreSync) Create(ctx context.Context, token *types.Token) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.Create(ctx, token) -} - -// Delete deletes the token with the given id. -func (s *TokenStoreSync) Delete(ctx context.Context, id int64) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.Delete(ctx, id) -} - -// DeleteForPrincipal deletes all tokens for a specific principal. -func (s *TokenStoreSync) DeleteForPrincipal(ctx context.Context, principalID int64) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.DeleteForPrincipal(ctx, principalID) -} - -// Count returns a count of tokens of a specifc type for a specific principal. -func (s *TokenStoreSync) Count(ctx context.Context, principalID int64, - tokenType enum.TokenType) (int64, error) { - mutex.Lock() - defer mutex.Unlock() - return s.base.Count(ctx, principalID, tokenType) -} - -// List returns a list of tokens of a specific type for a specific principal. -func (s *TokenStoreSync) List(ctx context.Context, principalID int64, - tokenType enum.TokenType) ([]*types.Token, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.List(ctx, principalID, tokenType) -} diff --git a/internal/store/database/user.go b/internal/store/database/user.go index 0bb65440a..fb6226ec1 100644 --- a/internal/store/database/user.go +++ b/internal/store/database/user.go @@ -6,10 +6,10 @@ package database import ( "context" - "database/sql" "fmt" "github.com/harness/gitness/internal/store" + "github.com/harness/gitness/internal/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -35,8 +35,7 @@ func NewUserStore(db *sqlx.DB, uidTransformation store.PrincipalUIDTransformatio } } -// UserStore implements a UserStore backed by a relational -// database. +// UserStore implements a UserStore backed by a relational database. type UserStore struct { db *sqlx.DB uidTransformation store.PrincipalUIDTransformation @@ -44,10 +43,13 @@ type UserStore struct { // Find finds the user by id. func (s *UserStore) Find(ctx context.Context, id int64) (*types.User, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(user) - if err := s.db.GetContext(ctx, dst, userSelectID, id); err != nil { + if err := db.GetContext(ctx, dst, userSelectID, id); err != nil { return nil, processSQLErrorf(err, "Select by id query failed") } + return s.mapDBUser(dst), nil } @@ -61,19 +63,25 @@ func (s *UserStore) FindUID(ctx context.Context, uid string) (*types.User, error return nil, store.ErrResourceNotFound } + db := dbtx.GetAccessor(ctx, s.db) + dst := new(user) - if err = s.db.GetContext(ctx, dst, userSelectUIDUnique, uidUnique); err != nil { + if err = db.GetContext(ctx, dst, userSelectUIDUnique, uidUnique); err != nil { return nil, processSQLErrorf(err, "Select by uid query failed") } + return s.mapDBUser(dst), nil } // FindEmail finds the user by email. func (s *UserStore) FindEmail(ctx context.Context, email string) (*types.User, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := new(user) - if err := s.db.GetContext(ctx, dst, userSelectEmail, email); err != nil { + if err := db.GetContext(ctx, dst, userSelectEmail, email); err != nil { return nil, processSQLErrorf(err, "Select by email query failed") } + return s.mapDBUser(dst), nil } @@ -84,12 +92,14 @@ func (s *UserStore) Create(ctx context.Context, user *types.User) error { return fmt.Errorf("failed to map db user: %w", err) } - query, arg, err := s.db.BindNamed(userInsert, dbUser) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(userInsert, dbUser) if err != nil { return processSQLErrorf(err, "Failed to bind user object") } - if err = s.db.QueryRowContext(ctx, query, arg...).Scan(&user.ID); err != nil { + if err = db.QueryRowContext(ctx, query, arg...).Scan(&user.ID); err != nil { return processSQLErrorf(err, "Insert query failed") } @@ -103,12 +113,14 @@ func (s *UserStore) Update(ctx context.Context, user *types.User) error { return fmt.Errorf("failed to map db user: %w", err) } - query, arg, err := s.db.BindNamed(userUpdate, dbUser) + db := dbtx.GetAccessor(ctx, s.db) + + query, arg, err := db.BindNamed(userUpdate, dbUser) if err != nil { return processSQLErrorf(err, "Failed to bind user object") } - if _, err = s.db.ExecContext(ctx, query, arg...); err != nil { + if _, err = db.ExecContext(ctx, query, arg...); err != nil { return processSQLErrorf(err, "Update query failed") } @@ -117,28 +129,25 @@ func (s *UserStore) Update(ctx context.Context, user *types.User) error { // Delete deletes the user. func (s *UserStore) Delete(ctx context.Context, id int64) error { - tx, err := s.db.BeginTx(ctx, nil) - if err != nil { - return processSQLErrorf(err, "Failed to start a new transaction") - } - defer func(tx *sql.Tx) { - _ = tx.Rollback() - }(tx) - // delete the user - if _, err = tx.ExecContext(ctx, userDelete, id); err != nil { + db := dbtx.GetAccessor(ctx, s.db) + + if _, err := db.ExecContext(ctx, userDelete, id); err != nil { return processSQLErrorf(err, "The delete query failed") } - return tx.Commit() + + return nil } // List returns a list of users. func (s *UserStore) List(ctx context.Context, opts *types.UserFilter) ([]*types.User, error) { + db := dbtx.GetAccessor(ctx, s.db) + dst := []*user{} // if the user does not provide any customer filter // or sorting we use the default select statement. if opts.Sort == enum.UserAttrNone { - err := s.db.SelectContext(ctx, &dst, userSelect, limit(opts.Size), offset(opts.Page, opts.Size)) + err := db.SelectContext(ctx, &dst, userSelect, limit(opts.Size), offset(opts.Page, opts.Size)) if err != nil { return nil, processSQLErrorf(err, "Failed executing default list query") } @@ -173,7 +182,7 @@ func (s *UserStore) List(ctx context.Context, opts *types.UserFilter) ([]*types. return nil, errors.Wrap(err, "Failed to convert query to sql") } - if err = s.db.SelectContext(ctx, &dst, sql); err != nil { + if err = db.SelectContext(ctx, &dst, sql); err != nil { return nil, processSQLErrorf(err, "Failed executing custom list query") } @@ -182,11 +191,14 @@ func (s *UserStore) List(ctx context.Context, opts *types.UserFilter) ([]*types. // Count returns a count of users. func (s *UserStore) Count(ctx context.Context) (int64, error) { + db := dbtx.GetAccessor(ctx, s.db) + var count int64 - err := s.db.QueryRowContext(ctx, userCount).Scan(&count) + err := db.QueryRowContext(ctx, userCount).Scan(&count) if err != nil { return 0, processSQLErrorf(err, "Failed executing count query") } + return count, nil } diff --git a/internal/store/database/user_sync.go b/internal/store/database/user_sync.go deleted file mode 100644 index 99e9bfc78..000000000 --- a/internal/store/database/user_sync.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2022 Harness Inc. All rights reserved. -// Use of this source code is governed by the Polyform Free Trial License -// that can be found in the LICENSE.md file for this repository. - -package database - -import ( - "context" - - "github.com/harness/gitness/internal/store" - "github.com/harness/gitness/internal/store/database/mutex" - "github.com/harness/gitness/types" -) - -var _ store.UserStore = (*UserStoreSync)(nil) - -// NewUserStoreSync returns a new UserStoreSync. -func NewUserStoreSync(store *UserStore) *UserStoreSync { - return &UserStoreSync{base: store} -} - -// UserStoreSync synronizes read and write access to the -// user store. This prevents race conditions when the database -// type is sqlite3. -type UserStoreSync struct{ base *UserStore } - -// Find finds the user by id. -func (s *UserStoreSync) Find(ctx context.Context, id int64) (*types.User, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.Find(ctx, id) -} - -// FindUID finds the user by uid. -func (s *UserStoreSync) FindUID(ctx context.Context, uid string) (*types.User, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.FindUID(ctx, uid) -} - -// FindEmail finds the user by email. -func (s *UserStoreSync) FindEmail(ctx context.Context, email string) (*types.User, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.FindEmail(ctx, email) -} - -// List returns a list of users. -func (s *UserStoreSync) List(ctx context.Context, opts *types.UserFilter) ([]*types.User, error) { - mutex.RLock() - defer mutex.RUnlock() - return s.base.List(ctx, opts) -} - -// Create saves the user details. -func (s *UserStoreSync) Create(ctx context.Context, user *types.User) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.Create(ctx, user) -} - -// Update updates the user details. -func (s *UserStoreSync) Update(ctx context.Context, user *types.User) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.Update(ctx, user) -} - -// Delete deletes the user. -func (s *UserStoreSync) Delete(ctx context.Context, id int64) error { - mutex.Lock() - defer mutex.Unlock() - return s.base.Delete(ctx, id) -} - -// Count returns a count of users. -func (s *UserStoreSync) Count(ctx context.Context) (int64, error) { - mutex.Lock() - defer mutex.Unlock() - return s.base.Count(ctx) -} diff --git a/internal/store/database/user_test.go b/internal/store/database/user_test.go index 622f281fd..8af8041c0 100644 --- a/internal/store/database/user_test.go +++ b/internal/store/database/user_test.go @@ -38,7 +38,7 @@ func TestUser(t *testing.T) { return } - userStoreSync := NewUserStoreSync(NewUserStore(db, store.ToLowerPrincipalUIDTransformation)) + userStoreSync := NewUserStore(db, store.ToLowerPrincipalUIDTransformation) t.Run("create", testUserCreate(userStoreSync)) t.Run("duplicate", testUserDuplicate(userStoreSync)) t.Run("count", testUserCount(userStoreSync)) @@ -244,8 +244,8 @@ func testUserDelete(s store.UserStore) func(t *testing.T) { t.Error(err) return } - if _, err = s.Find(ctx, 1); errors.Is(err, store.ErrResourceNotFound) { - t.Errorf("Expected sql.ErrNoRows got %s", err) + if _, err = s.Find(ctx, 1); !errors.Is(err, store.ErrResourceNotFound) { + t.Errorf("Expected store.ErrResourceNotFound got %s", err) } } } diff --git a/internal/store/database/wire.go b/internal/store/database/wire.go index 4fc1af8cc..cc761621a 100644 --- a/internal/store/database/wire.go +++ b/internal/store/database/wire.go @@ -44,39 +44,18 @@ func ProvideDatabase(ctx context.Context, config *types.Config) (*sqlx.DB, error // ProvideUserStore provides a user store. func ProvideUserStore(db *sqlx.DB, uidTransformation store.PrincipalUIDTransformation) store.UserStore { - switch db.DriverName() { - case postgres: - return NewUserStore(db, uidTransformation) - default: - return NewUserStoreSync( - NewUserStore(db, uidTransformation), - ) - } + return NewUserStore(db, uidTransformation) } // ProvideServiceAccountStore provides a service account store. func ProvideServiceAccountStore(db *sqlx.DB, uidTransformation store.PrincipalUIDTransformation) store.ServiceAccountStore { - switch db.DriverName() { - case postgres: - return NewServiceAccountStore(db, uidTransformation) - default: - return NewServiceAccountStoreSync( - NewServiceAccountStore(db, uidTransformation), - ) - } + return NewServiceAccountStore(db, uidTransformation) } // ProvideServiceStore provides a service store. func ProvideServiceStore(db *sqlx.DB, uidTransformation store.PrincipalUIDTransformation) store.ServiceStore { - switch db.DriverName() { - case postgres: - return NewServiceStore(db, uidTransformation) - default: - return NewServiceStoreSync( - NewServiceStore(db, uidTransformation), - ) - } + return NewServiceStore(db, uidTransformation) } // ProvideSpaceStore provides a space store. @@ -105,14 +84,7 @@ func ProvideRepoStore(db *sqlx.DB, pathTransformation store.PathTransformation) // ProvideTokenStore provides a token store. func ProvideTokenStore(db *sqlx.DB) store.TokenStore { - switch db.DriverName() { - case postgres: - return NewTokenStore(db) - default: - return NewTokenStoreSync( - NewTokenStore(db), - ) - } + return NewTokenStore(db) } // ProvidePullReqStore provides a pull request store.