fix: [CDE-290]: modify list function for gitspaces (#2908)

* feat: [CDE-332]: debugging
* feat: [CDE-332]: debugging
* feat: [CDE-332]: debugging
* feat: [CDE-332]: debugging
* feat: [CDE-332]: fix subquery no alias
* feat: [CDE-332]: fix subquery no alias
* feat: [CDE-332]: fix subquery no alias
* feat: [CDE-332]: fix subquery no alias
* feat: [CDE-332]: remove duplication of code
* feat: [CDE-332]: remove duplication of code
* feat: [CDE-332]: remove duplication of code
* 

feat: [CDE-332]: remove duplication of code
* 





modify list all
* 





fix lint
* 





add sorting
* 





modify list function
This commit is contained in:
Deepak Bhatt 2024-11-01 06:07:53 +00:00 committed by Harness
parent 9c442d0c9b
commit 516fadfe8f
11 changed files with 289 additions and 267 deletions

View File

@ -32,9 +32,13 @@ func (c *Controller) ListAllGitspaces( // nolint:gocognit
ctx context.Context,
session *auth.Session,
) ([]*types.GitspaceConfig, error) {
filter := &types.GitspaceFilter{
GitspaceInstanceFilter: types.GitspaceInstanceFilter{UserIdentifier: session.Principal.UID},
}
var result []*types.GitspaceConfig
err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) {
allGitspaceConfigs, err := c.gitspaceConfigStore.ListAll(ctx, session.Principal.UID)
allGitspaceConfigs, err := c.gitspaceConfigStore.ListWithLatestInstance(ctx, filter)
if err != nil {
return fmt.Errorf("failed to list gitspace configs: %w", err)
}
@ -61,10 +65,7 @@ func (c *Controller) ListAllGitspaces( // nolint:gocognit
return err
}
finalGitspaceConfigs, err := c.filterAndPopulateInstanceDetails(ctx, allGitspaceConfigs, authorizedSpaceIDs)
if err != nil {
return err
}
finalGitspaceConfigs := c.filter(allGitspaceConfigs, authorizedSpaceIDs)
result = finalGitspaceConfigs
@ -75,48 +76,14 @@ func (c *Controller) ListAllGitspaces( // nolint:gocognit
return nil, err
}
for _, gitspaceConfig := range result {
gitspaceConfig.BranchURL = c.gitspaceSvc.GetBranchURL(ctx, gitspaceConfig)
}
return result, nil
}
func (c *Controller) filterAndPopulateInstanceDetails(
ctx context.Context,
func (c *Controller) filter(
allGitspaceConfigs []*types.GitspaceConfig,
authorizedSpaceIDs map[int64]bool,
) ([]*types.GitspaceConfig, error) {
authorizedGitspaceConfigs := c.getAuthorizedGitspaceConfigs(allGitspaceConfigs, authorizedSpaceIDs)
gitspaceInstancesMap, err := c.getLatestInstanceMap(ctx, authorizedGitspaceConfigs)
if err != nil {
return nil, err
}
var result []*types.GitspaceConfig
for _, gitspaceConfig := range authorizedGitspaceConfigs {
instance := gitspaceInstancesMap[gitspaceConfig.ID]
gitspaceConfig.GitspaceInstance = instance
if instance != nil {
gitspaceStateType, stateErr := enum.GetGitspaceStateFromInstance(instance.State, instance.Updated)
if stateErr != nil {
return nil, stateErr
}
gitspaceConfig.State = gitspaceStateType
instance.SpacePath = gitspaceConfig.SpacePath
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
result = append(result, gitspaceConfig)
}
return result, nil
) []*types.GitspaceConfig {
return c.getAuthorizedGitspaceConfigs(allGitspaceConfigs, authorizedSpaceIDs)
}
func (c *Controller) getAuthorizedGitspaceConfigs(
@ -150,26 +117,3 @@ func (c *Controller) getAuthorizedSpaces(
return authorizedSpaceIDs, nil
}
func (c *Controller) getLatestInstanceMap(
ctx context.Context,
authorizedGitspaceConfigs []*types.GitspaceConfig,
) (map[int64]*types.GitspaceInstance, error) {
var authorizedConfigIDs = make([]int64, 0)
for _, config := range authorizedGitspaceConfigs {
authorizedConfigIDs = append(authorizedConfigIDs, config.ID)
}
var gitspaceInstances, err = c.gitspaceInstanceStore.FindAllLatestByGitspaceConfigID(ctx, authorizedConfigIDs)
if err != nil {
return nil, err
}
var gitspaceInstancesMap = make(map[int64]*types.GitspaceInstance)
for _, gitspaceEntry := range gitspaceInstances {
gitspaceInstancesMap[gitspaceEntry.GitSpaceConfigID] = gitspaceEntry
}
return gitspaceInstancesMap, nil
}

View File

@ -28,7 +28,7 @@ func (c *Controller) ListGitspaces(
ctx context.Context,
session *auth.Session,
spaceRef string,
filter types.ListQueryFilter,
filter types.GitspaceFilter,
) ([]*types.GitspaceConfig, int64, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
@ -38,5 +38,10 @@ func (c *Controller) ListGitspaces(
if err != nil {
return nil, 0, fmt.Errorf("failed to authorize gitspace: %w", err)
}
return c.gitspaceSvc.ListGitspacesForSpace(ctx, space, session.Principal.UID, filter)
filter.UserIdentifier = session.Principal.UID
filter.SpaceIDs = []int64{space.ID}
filter.IncludeMarkedForDeletion = false
return c.gitspaceSvc.ListGitspacesForSpace(ctx, space, filter)
}

View File

@ -31,13 +31,13 @@ func HandleListGitspaces(spacesCtrl *space.Controller) http.HandlerFunc {
render.TranslatedUserError(ctx, w, err)
return
}
filter := request.ParseListQueryFilterFromRequest(r)
filter := request.ParseGitspaceFilter(r)
repos, totalCount, err := spacesCtrl.ListGitspaces(ctx, session, spaceRef, filter)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
render.Pagination(r, w, filter.Page, filter.Size, int(totalCount))
render.Pagination(r, w, filter.QueryFilter.Page, filter.QueryFilter.Size, int(totalCount))
render.JSON(w, http.StatusOK, repos)
}
}

View File

@ -16,6 +16,9 @@ package request
import (
"net/http"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
const (
@ -25,3 +28,19 @@ const (
func GetGitspaceRefFromPath(r *http.Request) (string, error) {
return PathParamOrError(r, PathParamGitspaceIdentifier)
}
// ParseGitspaceSort extracts the gitspace sort parameter from the url.
func ParseGitspaceSort(r *http.Request) enum.GitspaceSort {
return enum.ParseGitspaceSort(
r.URL.Query().Get(QueryParamSort),
)
}
// ParseGitspaceFilter extracts the gitspace filter from the url.
func ParseGitspaceFilter(r *http.Request) types.GitspaceFilter {
return types.GitspaceFilter{
QueryFilter: ParseListQueryFilterFromRequest(r),
Sort: ParseGitspaceSort(r),
Order: ParseOrder(r),
}
}

View File

@ -25,7 +25,6 @@ import (
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
@ -69,70 +68,37 @@ type Service struct {
func (c *Service) ListGitspacesForSpace(
ctx context.Context,
space *types.Space,
userIdentifier string,
filter types.ListQueryFilter,
filter types.GitspaceFilter,
) ([]*types.GitspaceConfig, int64, error) {
gitspaceFilter := &types.GitspaceFilter{
QueryFilter: filter,
UserID: userIdentifier,
SpaceIDs: []int64{space.ID},
}
var gitspaceConfigs []*types.GitspaceConfig
var count int64
err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) {
gitspaceConfigs, err = c.gitspaceConfigStore.List(ctx, gitspaceFilter)
gitspaceConfigs, err = c.gitspaceConfigStore.ListWithLatestInstance(ctx, &filter)
if err != nil {
return fmt.Errorf("failed to list gitspace configs: %w", err)
}
count, err = c.gitspaceConfigStore.Count(ctx, gitspaceFilter)
count, err = c.gitspaceConfigStore.Count(ctx, &filter)
if err != nil {
return fmt.Errorf("failed to count gitspaces in space: %w", err)
}
gitspaceInstancesMap, err := c.getLatestInstanceMap(ctx, gitspaceConfigs)
if err != nil {
return err
}
for _, gitspaceConfig := range gitspaceConfigs {
instance := gitspaceInstancesMap[gitspaceConfig.ID]
gitspaceConfig.GitspaceInstance = instance
gitspaceConfig.SpacePath = space.Path
if instance != nil {
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State, instance.Updated)
if err != nil {
return err
}
gitspaceConfig.State = gitspaceStateType
instance.SpacePath = gitspaceConfig.SpacePath
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
gitspaceConfig.BranchURL = c.GetBranchURL(ctx, gitspaceConfig)
}
return nil
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, 0, err
}
return gitspaceConfigs, count, nil
}
func (c *Service) getLatestInstanceMap(
ctx context.Context,
gitspaceConfigs []*types.GitspaceConfig,
) (map[int64]*types.GitspaceInstance, error) {
var gitspaceConfigIDs = make([]int64, 0)
for idx := 0; idx < len(gitspaceConfigs); idx++ {
gitspaceConfigIDs = append(gitspaceConfigIDs, gitspaceConfigs[idx].ID)
for _, gitspaceConfig := range gitspaceConfigs {
gitspaceConfig.SpacePath = space.Path
if gitspaceConfig.GitspaceInstance != nil {
gitspaceConfig.GitspaceInstance.SpacePath = space.Path
}
gitspaceConfig.BranchURL = c.GetBranchURL(ctx, gitspaceConfig)
}
var gitspaceInstances, err = c.gitspaceInstanceStore.FindAllLatestByGitspaceConfigID(ctx, gitspaceConfigIDs)
if err != nil {
return nil, err
}
var gitspaceInstancesMap = make(map[int64]*types.GitspaceInstance)
for _, gitspaceEntry := range gitspaceInstances {
gitspaceInstancesMap[gitspaceEntry.GitSpaceConfigID] = gitspaceEntry
}
return gitspaceInstancesMap, nil
return gitspaceConfigs, count, nil
}
func (c *Service) GetBranchURL(ctx context.Context, config *types.GitspaceConfig) string {

View File

@ -662,14 +662,12 @@ type (
// Update tries to update a gitspace config in the datastore with optimistic locking.
Update(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error
// List lists the gitspace configs present in a parent space ID in the datastore.
List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceConfig, error)
// ListWithLatestInstance returns gitspace configs for the given filter with the latest gitspace instance
// information.
ListWithLatestInstance(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceConfig, error)
// Count the number of gitspace configs in a space matching the given filter.
Count(ctx context.Context, filter *types.GitspaceFilter) (int64, error)
// ListAll lists all the gitspace configs present for a user in the given spaces in the datastore.
ListAll(ctx context.Context, userUID string) ([]*types.GitspaceConfig, error)
}
GitspaceInstanceStore interface {
@ -692,13 +690,10 @@ type (
Update(ctx context.Context, gitspaceInstance *types.GitspaceInstance) error
// List lists the gitspace instance present in a parent space ID in the datastore.
List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceInstance, error)
List(ctx context.Context, filter *types.GitspaceInstanceFilter) ([]*types.GitspaceInstance, error)
// ListDead lists dead gitspace instances whose heartbeat stopped coming after the given time.
ListDead(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceInstance, error)
// FetchInactiveGitspaceConfigs lists the inactive gitspace instance present in the datastore
FetchInactiveGitspaceConfigs(ctx context.Context, filter *types.GitspaceFilter) ([]int64, error)
// Count the number of gitspace instances in a space matching the given filter.
Count(ctx context.Context, filter *types.GitspaceInstanceFilter) (int64, error)
// List lists the latest gitspace instance present for the gitspace configs in the datastore.
FindAllLatestByGitspaceConfigID(

View File

@ -29,6 +29,7 @@ import (
"github.com/guregu/null"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
const (
@ -84,6 +85,12 @@ type gitspaceConfig struct {
IsMarkedForDeletion bool `db:"gconf_is_marked_for_deletion"`
}
type gitspaceConfigWithLatestInstance struct {
gitspaceConfig
// gitspace instance information
gitspaceInstance
}
var _ store.GitspaceConfigStore = (*gitspaceConfigStore)(nil)
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
@ -109,20 +116,10 @@ func (s gitspaceConfigStore) Count(ctx context.Context, filter *types.GitspaceFi
db := dbtx.GetAccessor(ctx, s.db)
countStmt := database.Builder.
Select("COUNT(*)").
From(gitspaceConfigsTable)
From(gitspaceConfigsTable).
PlaceholderFormat(squirrel.Dollar)
if !filter.IncludeDeleted {
countStmt = countStmt.Where(squirrel.Eq{"gconf_is_deleted": false})
}
if filter.UserID != "" {
countStmt = countStmt.Where(squirrel.Eq{"gconf_user_uid": filter.UserID})
}
if len(filter.SpaceIDs) > 0 {
countStmt = countStmt.Where(squirrel.Eq{"gconf_space_id": filter.SpaceIDs})
}
if filter.IncludeMarkedForDeletion {
countStmt = countStmt.Where(squirrel.Eq{"gconf_is_marked_for_deletion": true})
}
countStmt = addGitspaceFilter(countStmt, filter)
sql, args, err := countStmt.ToSql()
if err != nil {
@ -155,7 +152,7 @@ func (s gitspaceConfigStore) Find(ctx context.Context, id int64, includeDeleted
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace config for %d", id)
}
return s.mapToGitspaceConfig(ctx, dst)
return s.mapDBToGitspaceConfig(ctx, dst)
}
func (s gitspaceConfigStore) FindByIdentifier(
@ -179,7 +176,7 @@ func (s gitspaceConfigStore) FindByIdentifier(
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace config for %s", identifier)
}
return s.mapToGitspaceConfig(ctx, dst)
return s.mapDBToGitspaceConfig(ctx, dst)
}
func (s gitspaceConfigStore) Create(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error {
@ -271,63 +268,75 @@ func mapToInternalGitspaceConfig(config *types.GitspaceConfig) *gitspaceConfig {
}
}
func (s gitspaceConfigStore) List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceConfig, error) {
stmt := database.Builder.
Select(gitspaceConfigSelectColumns).
From(gitspaceConfigsTable)
// ListWithLatestInstance returns gitspace configs for the given filter with the latest gitspace instance information.
func (s gitspaceConfigStore) ListWithLatestInstance(
ctx context.Context,
filter *types.GitspaceFilter,
) ([]*types.GitspaceConfig, error) {
gitsSelectStr := getLatestInstanceQuery()
stmt := squirrel.Select(
gitspaceConfigSelectColumns,
gitspaceInstanceSelectColumns).
From(gitspaceConfigsTable).
LeftJoin("(" + gitsSelectStr +
") AS gits ON gitspace_configs.gconf_id = gits.gits_gitspace_config_id AND gits.rn = 1").
PlaceholderFormat(squirrel.Dollar)
stmt = addGitspaceFilter(stmt, filter)
stmt = addOrderBy(stmt, filter)
stmt = stmt.Limit(database.Limit(filter.QueryFilter.Size))
stmt = stmt.Offset(database.Offset(filter.QueryFilter.Page, filter.QueryFilter.Size))
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
var dst []*gitspaceConfigWithLatestInstance
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing list gitspace config query")
}
return s.ToGitspaceConfigs(ctx, dst)
}
func getLatestInstanceQuery() string {
return fmt.Sprintf("SELECT %s, %s FROM %s",
gitspaceInstanceSelectColumns,
"ROW_NUMBER() OVER (PARTITION BY gits_gitspace_config_id ORDER BY gits_created DESC) AS rn",
gitspaceInstanceTable,
)
}
func addGitspaceFilter(stmt squirrel.SelectBuilder, filter *types.GitspaceFilter) squirrel.SelectBuilder {
if !filter.IncludeDeleted {
stmt = stmt.Where(squirrel.Eq{"gconf_is_deleted": false})
}
if filter.UserID != "" {
stmt = stmt.Where(squirrel.Eq{"gconf_user_uid": filter.UserID})
if filter.UserIdentifier != "" {
stmt = stmt.Where(squirrel.Eq{"gconf_user_uid": filter.UserIdentifier})
}
if !filter.IncludeMarkedForDeletion {
stmt = stmt.Where(squirrel.Eq{"gconf_is_marked_for_deletion": false})
}
if len(filter.SpaceIDs) > 0 {
stmt = stmt.Where(squirrel.Eq{"gconf_space_id": filter.SpaceIDs})
}
if filter.IncludeMarkedForDeletion {
stmt = stmt.Where(squirrel.Eq{"gconf_is_marked_for_deletion": true})
}
queryFilter := filter.QueryFilter
stmt = stmt.Limit(database.Limit(queryFilter.Size))
stmt = stmt.Offset(database.Offset(queryFilter.Page, queryFilter.Size))
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
var dst []*gitspaceConfig
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list space query")
}
return s.mapToGitspaceConfigs(ctx, dst)
return stmt
}
func (s gitspaceConfigStore) ListAll(
ctx context.Context,
userUID string,
) ([]*types.GitspaceConfig, error) {
stmt := database.Builder.
Select(gitspaceConfigSelectColumns).
From(gitspaceConfigsTable).
Where(squirrel.Eq{"gconf_is_deleted": false}).
Where(squirrel.Eq{"gconf_user_uid": userUID})
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
func addOrderBy(stmt squirrel.SelectBuilder, filter *types.GitspaceFilter) squirrel.SelectBuilder {
switch filter.Sort {
case enum.GitspaceSortLastUsed:
return stmt.OrderBy("gits_last_used " + filter.Order.String())
case enum.GitspaceSortCreated:
return stmt.OrderBy("gconf_created " + filter.Order.String())
default:
return stmt.OrderBy("gits_last_used " + filter.Order.String())
}
db := dbtx.GetAccessor(ctx, s.db)
var dst []*gitspaceConfig
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list all query")
}
return s.mapToGitspaceConfigs(ctx, dst)
}
func (s gitspaceConfigStore) FindAll(ctx context.Context, ids []int64) ([]*types.GitspaceConfig, error) {
@ -348,7 +357,7 @@ func (s gitspaceConfigStore) FindAll(ctx context.Context, ids []int64) ([]*types
return s.mapToGitspaceConfigs(ctx, dst)
}
func (s *gitspaceConfigStore) mapToGitspaceConfig(
func (s gitspaceConfigStore) mapDBToGitspaceConfig(
ctx context.Context,
in *gitspaceConfig,
) (*types.GitspaceConfig, error) {
@ -362,7 +371,7 @@ func (s *gitspaceConfigStore) mapToGitspaceConfig(
AuthType: in.CodeAuthType,
AuthID: in.CodeAuthID,
}
var res = &types.GitspaceConfig{
var result = &types.GitspaceConfig{
ID: in.ID,
Identifier: in.Identifier,
Name: in.Name,
@ -378,30 +387,78 @@ func (s *gitspaceConfigStore) mapToGitspaceConfig(
ID: in.CreatedBy.Ptr(),
Identifier: in.UserUID},
}
if res.GitspaceUser.ID != nil {
author, _ := s.pCache.Get(ctx, *res.GitspaceUser.ID)
if result.GitspaceUser.ID != nil {
author, _ := s.pCache.Get(ctx, *result.GitspaceUser.ID)
if author != nil {
res.GitspaceUser.DisplayName = author.DisplayName
res.GitspaceUser.Email = author.Email
result.GitspaceUser.DisplayName = author.DisplayName
result.GitspaceUser.Email = author.Email
}
}
if resource, err := s.rCache.Get(ctx, in.InfraProviderResourceID); err == nil {
res.InfraProviderResource = *resource
result.InfraProviderResource = *resource
} else {
return nil, fmt.Errorf("couldn't set resource to the config in DB: %s", in.Identifier)
}
return res, nil
return result, nil
}
func (s *gitspaceConfigStore) mapToGitspaceConfigs(
func (s gitspaceConfigStore) ToGitspaceConfig(
ctx context.Context,
in *gitspaceConfigWithLatestInstance,
) (*types.GitspaceConfig, error) {
var result, err = s.mapDBToGitspaceConfig(ctx, &in.gitspaceConfig)
if err != nil {
return nil, err
}
instance, err := mapDBToGitspaceInstance(ctx, &in.gitspaceInstance)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msgf("Failed to convert to gitspace instance, gitspace configID: %d",
in.gitspaceInstance.ID,
)
instance = nil
}
if instance != nil {
gitspaceStateType, err2 := enum.GetGitspaceStateFromInstance(
instance.State,
instance.Updated,
)
if err2 != nil {
return nil, err2
}
result.State = gitspaceStateType
} else {
result.State = enum.GitspaceStateUninitialized
}
result.GitspaceInstance = instance
return result, nil
}
func (s gitspaceConfigStore) mapToGitspaceConfigs(
ctx context.Context,
configs []*gitspaceConfig,
) ([]*types.GitspaceConfig, error) {
var err error
res := make([]*types.GitspaceConfig, len(configs))
for i := range configs {
res[i], err = s.mapToGitspaceConfig(ctx, configs[i])
res[i], err = s.mapDBToGitspaceConfig(ctx, configs[i])
if err != nil {
return nil, err
}
}
return res, nil
}
func (s gitspaceConfigStore) ToGitspaceConfigs(
ctx context.Context,
configs []*gitspaceConfigWithLatestInstance,
) ([]*types.GitspaceConfig, error) {
var err error
res := make([]*types.GitspaceConfig, len(configs))
for i := range configs {
res[i], err = s.ToGitspaceConfig(ctx, configs[i])
if err != nil {
return nil, err
}

View File

@ -166,7 +166,7 @@ func (g gitspaceInstanceStore) Find(ctx context.Context, id int64) (*types.Gitsp
if err := db.GetContext(ctx, gitspace, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace %d", id)
}
return g.mapToGitspaceInstance(ctx, gitspace)
return mapDBToGitspaceInstance(ctx, gitspace)
}
func (g gitspaceInstanceStore) FindByIdentifier(
@ -187,7 +187,7 @@ func (g gitspaceInstanceStore) FindByIdentifier(
if err := db.GetContext(ctx, gitspace, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace %s", identifier)
}
return g.mapToGitspaceInstance(ctx, gitspace)
return mapDBToGitspaceInstance(ctx, gitspace)
}
func (g gitspaceInstanceStore) Create(ctx context.Context, gitspaceInstance *types.GitspaceInstance) error {
@ -276,34 +276,18 @@ func (g gitspaceInstanceStore) FindLatestByGitspaceConfigID(
return nil, database.ProcessSQLErrorf(
ctx, err, "Failed to find latest gitspace instance for %d", gitspaceConfigID)
}
return g.mapToGitspaceInstance(ctx, gitspace)
return mapDBToGitspaceInstance(ctx, gitspace)
}
func (g gitspaceInstanceStore) List(
ctx context.Context,
filter *types.GitspaceFilter,
filter *types.GitspaceInstanceFilter,
) ([]*types.GitspaceInstance, error) {
stmt := database.Builder.
Select(gitspaceInstanceSelectColumns).
From(gitspaceInstanceTable).
OrderBy("gits_created ASC")
if len(filter.SpaceIDs) > 0 {
stmt = stmt.Where(squirrel.Eq{"gits_space_id": filter.SpaceIDs})
}
if filter.UserID != "" {
stmt = stmt.Where(squirrel.Eq{"gits_user_id": filter.UserID})
}
if len(filter.State) > 0 {
stmt = stmt.Where(squirrel.Eq{"gits_state": filter.State})
}
if filter.Limit > 0 {
stmt = stmt.Limit(database.Limit(filter.Limit))
}
stmt = addGitspaceInstanceFilter(stmt, filter)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
@ -316,53 +300,24 @@ func (g gitspaceInstanceStore) List(
return g.mapToGitspaceInstances(ctx, dst)
}
func (g gitspaceInstanceStore) ListDead(
ctx context.Context,
filter *types.GitspaceFilter,
) ([]*types.GitspaceInstance, error) {
stmt := database.Builder.
Select(gitspaceInstanceSelectColumns).
From(gitspaceInstanceTable).
Where(squirrel.Lt{"gits_last_heartbeat": filter.LastHeartBeatBefore}).
Where(squirrel.Eq{"gits_state": filter.State}).
OrderBy("gits_created ASC")
sqlStr, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
var dst []*gitspaceInstance
func (g gitspaceInstanceStore) Count(ctx context.Context, filter *types.GitspaceInstanceFilter) (int64, error) {
db := dbtx.GetAccessor(ctx, g.db)
if err = db.SelectContext(ctx, &dst, sqlStr, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace instance list query")
}
return g.mapToGitspaceInstances(ctx, dst)
}
countStmt := database.Builder.
Select("COUNT(*)").
From(gitspaceInstanceTable)
func (g gitspaceInstanceStore) FetchInactiveGitspaceConfigs(
ctx context.Context,
filter *types.GitspaceFilter,
) ([]int64, error) {
stmt := database.Builder.
Select("gits_gitspace_config_id").
From(gitspaceInstanceTable).
Where(squirrel.Lt{"gits_last_used": filter.LastUsedBefore}).
Where(squirrel.Eq{"gits_state": filter.State}).
OrderBy("gits_created ASC")
if filter.Limit > 0 {
stmt = stmt.Limit(database.Limit(filter.Limit))
}
sql, args, err := stmt.ToSql()
countStmt = addGitspaceInstanceFilter(countStmt, filter)
sql, args, err := countStmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
return 0, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, g.db)
var dst []int64
if err := db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace instance list query")
var count int64
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, database.ProcessSQLErrorf(ctx, err, "Failed executing custom count query")
}
return dst, nil
return count, nil
}
func (g gitspaceInstanceStore) FindAllLatestByGitspaceConfigID(
@ -399,7 +354,33 @@ func (g gitspaceInstanceStore) FindAllLatestByGitspaceConfigID(
return g.mapToGitspaceInstances(ctx, dst)
}
func (g gitspaceInstanceStore) mapToGitspaceInstance(
func addGitspaceInstanceFilter(
stmt squirrel.SelectBuilder,
filter *types.GitspaceInstanceFilter,
) squirrel.SelectBuilder {
if len(filter.SpaceIDs) > 0 {
stmt = stmt.Where(squirrel.Eq{"gits_space_id": filter.SpaceIDs})
}
if filter.UserIdentifier != "" {
stmt = stmt.Where(squirrel.Eq{"gits_user_id": filter.UserIdentifier})
}
if filter.LastHeartBeatBefore > 0 {
stmt = stmt.Where(squirrel.Lt{"gits_last_heartbeat": filter.LastHeartBeatBefore})
}
if len(filter.States) > 0 {
stmt = stmt.Where(squirrel.Eq{"gits_state": filter.States})
}
if filter.Limit > 0 {
stmt = stmt.Limit(database.Limit(filter.Limit))
}
return stmt
}
func mapDBToGitspaceInstance(
_ context.Context,
in *gitspaceInstance,
) (*types.GitspaceInstance, error) {
@ -434,7 +415,7 @@ func (g gitspaceInstanceStore) mapToGitspaceInstances(
var err error
res := make([]*types.GitspaceInstance, len(instances))
for i := range instances {
res[i], err = g.mapToGitspaceInstance(ctx, instances[i])
res[i], err = mapDBToGitspaceInstance(ctx, instances[i])
if err != nil {
return nil, err
}

View File

@ -62,6 +62,7 @@ const (
desc = "desc"
descending = "descending"
value = "value"
lastUsed = "last_used"
)
func toInterfaceSlice[T interface{}](vals []T) []interface{} {

48
types/enum/gitspace.go Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package enum
import (
"strings"
)
// GitspaceSort represents gitspace sort order.
type GitspaceSort string
// GitspaceSort enumeration.
const (
GitspaceSortLastUsed GitspaceSort = lastUsed
GitspaceSortCreated GitspaceSort = created
)
var GitspaceSorts = sortEnum([]GitspaceSort{
GitspaceSortLastUsed,
GitspaceSortCreated,
})
func (GitspaceSort) Enum() []interface{} { return toInterfaceSlice(GitspaceSorts) }
// ParseGitspaceSort parses the gitspace sort attribute string
// and returns the equivalent enumeration.
func ParseGitspaceSort(s string) GitspaceSort {
switch strings.ToLower(s) {
case lastUsed:
return GitspaceSortLastUsed
case created, createdAt:
return GitspaceSortCreated
default:
return GitspaceSortLastUsed
}
}

View File

@ -82,12 +82,18 @@ type GitspaceInstance struct {
type GitspaceFilter struct {
QueryFilter ListQueryFilter
UserID string
LastUsedBefore int64
LastHeartBeatBefore int64
State []enum.GitspaceInstanceStateType
SpaceIDs []int64
Sort enum.GitspaceSort `json:"sort"`
Order enum.Order `json:"order"`
IncludeDeleted bool
IncludeMarkedForDeletion bool
Limit int
GitspaceInstanceFilter
}
type GitspaceInstanceFilter struct {
UserIdentifier string
LastUsedBefore int64
LastHeartBeatBefore int64
States []enum.GitspaceInstanceStateType
SpaceIDs []int64
Limit int
}