feat(subscription): use a recursive cte to fetch subscriptions of parent projects
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:
parent
22933dac4a
commit
fe27dd59ad
@ -540,19 +540,24 @@ func getSavedFilterProjects(s *xorm.Session, doer *user.User) (savedFiltersProje
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAllParentProjects returns all parents of a given project
|
// GetAllParentProjects returns all parents of a given project
|
||||||
func (p *Project) GetAllParentProjects(s *xorm.Session) (err error) {
|
func GetAllParentProjects(s *xorm.Session, projectID int64) (allProjects map[int64]*Project, err error) {
|
||||||
if p.ParentProjectID == 0 {
|
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
|
return
|
||||||
}
|
|
||||||
|
|
||||||
parent, err := GetProjectSimpleByID(s, p.ParentProjectID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.ParentProject = parent
|
|
||||||
|
|
||||||
return parent.GetAllParentProjects(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// addProjectDetails adds owner user objects and project tasks to all projects in the slice
|
// 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)
|
allProjects, err := GetAllParentProjects(s, project.ParentProjectID)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent *Project
|
var parent *Project
|
||||||
|
@ -301,20 +301,18 @@ func GetSubscriptionsForProjects(s *xorm.Session, projects []*Project, a web.Aut
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ps[p.ID].GetAllParentProjects(s)
|
parents, err := GetAllParentProjects(s, p.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parentIDs := []int64{}
|
// Walk the tree up until we reach the top
|
||||||
var parent = ps[p.ID].ParentProject
|
var parent = parents[p.ParentProjectID] // parent now has a pointer…
|
||||||
|
ps[p.ID].ParentProject = parents[p.ParentProjectID]
|
||||||
for parent != nil {
|
for parent != nil {
|
||||||
parentIDs = append(parentIDs, parent.ID)
|
allProjectIDs = append(allProjectIDs, parent.ID)
|
||||||
parent = parent.ParentProject
|
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
|
var subscriptions []*Subscription
|
||||||
|
Loading…
x
Reference in New Issue
Block a user