feat(subscription): use a recursive cte to fetch subscriptions of parent projects
continuous-integration/drone/push Build is passing Details

Testing this locally resulted in improved response times from ~50ms to ~20ms when creating a project. It looks like even though the code running these sql queries uses different go routines, they affect each other (caused by IO or context switching?)
This commit is contained in:
kolaente 2024-03-03 15:31:42 +01:00
parent 22933dac4a
commit fe27dd59ad
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
2 changed files with 26 additions and 43 deletions

View File

@ -540,19 +540,24 @@ func getSavedFilterProjects(s *xorm.Session, doer *user.User) (savedFiltersProje
}
// GetAllParentProjects returns all parents of a given project
func (p *Project) GetAllParentProjects(s *xorm.Session) (err error) {
if p.ParentProjectID == 0 {
return
}
parent, err := GetProjectSimpleByID(s, p.ParentProjectID)
if err != nil {
return err
}
p.ParentProject = parent
return parent.GetAllParentProjects(s)
func GetAllParentProjects(s *xorm.Session, projectID int64) (allProjects map[int64]*Project, err error) {
allProjects = make(map[int64]*Project)
err = s.SQL(`WITH RECURSIVE all_projects AS (
SELECT
p.*
FROM
projects p
WHERE
p.id = ?
UNION ALL
SELECT
p.*
FROM
projects p
INNER JOIN all_projects pc ON p.ID = pc.parent_project_id
)
SELECT DISTINCT * FROM all_projects`, projectID).Find(&allProjects)
return
}
// addProjectDetails adds owner user objects and project tasks to all projects in the slice
@ -667,29 +672,9 @@ func checkProjectBeforeUpdateOrDelete(s *xorm.Session, project *Project) (err er
}
}
allProjects := make(map[int64]*Project)
err = s.SQL(`WITH RECURSIVE all_projects AS (
SELECT
p.id,
p.parent_project_id
FROM
projects p
WHERE
p.id = ?
UNION ALL
SELECT
p.id,
p.parent_project_id
FROM
projects p
INNER JOIN all_projects pc ON p.ID = pc.parent_project_id
)
SELECT
*
FROM
all_projects`, project.ParentProjectID).Find(&allProjects)
allProjects, err := GetAllParentProjects(s, project.ParentProjectID)
if err != nil {
return
return err
}
var parent *Project

View File

@ -301,20 +301,18 @@ func GetSubscriptionsForProjects(s *xorm.Session, projects []*Project, a web.Aut
continue
}
err = ps[p.ID].GetAllParentProjects(s)
parents, err := GetAllParentProjects(s, p.ID)
if err != nil {
return nil, err
}
parentIDs := []int64{}
var parent = ps[p.ID].ParentProject
// Walk the tree up until we reach the top
var parent = parents[p.ParentProjectID] // parent now has a pointer…
ps[p.ID].ParentProject = parents[p.ParentProjectID]
for parent != nil {
parentIDs = append(parentIDs, parent.ID)
parent = parent.ParentProject
allProjectIDs = append(allProjectIDs, parent.ID)
parent = parents[parent.ParentProjectID] // … which means we can update it here and then update the pointer in the map
}
// Now we have all parent ids
allProjectIDs = append(allProjectIDs, parentIDs...) // the child project id is already in there
}
var subscriptions []*Subscription