Better efficency for loading teams (#128)
Fix staticcheck Better performance for getting teams on a namespace Better performance for getting teams on a list Fix lint Fix swagger Signed-off-by: kolaente <k@knt.li> Make loading a single full team more efficent Signed-off-by: kolaente <k@knt.li> Make loading teams more efficent Signed-off-by: kolaente <k@knt.li> Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/128
This commit is contained in:
@ -186,6 +186,16 @@ func (tl *TeamList) ReadAll(a web.Auth, search string, page int, perPage int) (r
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
teams := []*Team{}
|
||||
for _, t := range all {
|
||||
teams = append(teams, &t.Team)
|
||||
}
|
||||
|
||||
err = addMoreInfoToTeams(teams)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
totalItems, err = x.
|
||||
Table("teams").
|
||||
Join("INNER", "team_list", "team_id = teams.id").
|
||||
|
@ -171,6 +171,16 @@ func (tn *TeamNamespace) ReadAll(a web.Auth, search string, page int, perPage in
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
teams := []*Team{}
|
||||
for _, t := range all {
|
||||
teams = append(teams, &t.Team)
|
||||
}
|
||||
|
||||
err = addMoreInfoToTeams(teams)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
numberOfTotalItems, err = x.Table("teams").
|
||||
Join("INNER", "team_namespaces", "team_id = teams.id").
|
||||
Where("team_namespaces.namespace_id = ?", tn.NamespaceID).
|
||||
|
@ -236,7 +236,7 @@ func (t *Task) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) {
|
||||
// @Param s query string false "Search assignees by their username."
|
||||
// @Param taskID path int true "Task ID"
|
||||
// @Security JWTKeyAuth
|
||||
// @Success 200 {array} models.User "The assignees"
|
||||
// @Success 200 {array} user.User "The assignees"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks/{taskID}/assignees [get]
|
||||
func (la *TaskAssginee) ReadAll(a web.Auth, search string, page int, perPage int) (result interface{}, resultCount int, numberOfTotalItems int64, err error) {
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
||||
// Team holds a team object
|
||||
@ -53,15 +54,6 @@ func (Team) TableName() string {
|
||||
|
||||
// AfterLoad gets the created by user object
|
||||
func (t *Team) AfterLoad() {
|
||||
// Get the owner
|
||||
t.CreatedBy, _ = user.GetUserByID(t.CreatedByID)
|
||||
|
||||
// Get all members
|
||||
x.Select("*").
|
||||
Table("users").
|
||||
Join("INNER", "team_members", "team_members.user_id = users.id").
|
||||
Where("team_id = ?", t.ID).
|
||||
Find(&t.Members)
|
||||
}
|
||||
|
||||
// TeamMember defines the relationship between a user and a team
|
||||
@ -93,23 +85,76 @@ func (TeamMember) TableName() string {
|
||||
type TeamUser struct {
|
||||
user.User `xorm:"extends"`
|
||||
// Whether or not the member is an admin of the team. See the docs for more about what a team admin can do
|
||||
Admin bool `json:"admin"`
|
||||
Admin bool `json:"admin"`
|
||||
TeamID int64 `json:"-"`
|
||||
}
|
||||
|
||||
// GetTeamByID gets a team by its ID
|
||||
func GetTeamByID(id int64) (team Team, err error) {
|
||||
func GetTeamByID(id int64) (team *Team, err error) {
|
||||
if id < 1 {
|
||||
return team, ErrTeamDoesNotExist{id}
|
||||
}
|
||||
|
||||
exists, err := x.Where("id = ?", id).Get(&team)
|
||||
t := Team{}
|
||||
|
||||
exists, err := x.
|
||||
Where("id = ?", id).
|
||||
Get(&t)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
return team, ErrTeamDoesNotExist{id}
|
||||
return &t, ErrTeamDoesNotExist{id}
|
||||
}
|
||||
|
||||
teamSlice := []*Team{&t}
|
||||
err = addMoreInfoToTeams(teamSlice)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
team = &t
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func addMoreInfoToTeams(teams []*Team) (err error) {
|
||||
// Put the teams in a map to make assigning more info to it more efficient
|
||||
teamMap := make(map[int64]*Team, len(teams))
|
||||
var teamIDs []int64
|
||||
var ownerIDs []int64
|
||||
for _, team := range teams {
|
||||
teamMap[team.ID] = team
|
||||
teamIDs = append(teamIDs, team.ID)
|
||||
ownerIDs = append(ownerIDs, team.CreatedByID)
|
||||
}
|
||||
|
||||
// Get all owners and team members
|
||||
users := []*TeamUser{}
|
||||
err = x.Select("*").
|
||||
Table("users").
|
||||
Join("LEFT", "team_members", "team_members.user_id = users.id").
|
||||
Join("LEFT", "teams", "team_members.team_id = teams.id").
|
||||
Or(
|
||||
builder.In("team_id", teamIDs),
|
||||
builder.And(
|
||||
builder.In("users.id", ownerIDs),
|
||||
builder.Expr("teams.created_by_id = users.id"),
|
||||
builder.In("teams.id", teamIDs),
|
||||
),
|
||||
).
|
||||
Find(&users)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, u := range users {
|
||||
if _, exists := teamMap[u.TeamID]; !exists {
|
||||
continue
|
||||
}
|
||||
u.Email = ""
|
||||
teamMap[u.TeamID].CreatedBy = &u.User
|
||||
teamMap[u.TeamID].Members = append(teamMap[u.TeamID].Members, u)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -124,9 +169,12 @@ func GetTeamByID(id int64) (team Team, err error) {
|
||||
// @Success 200 {object} models.Team "The team"
|
||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the team"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /lists/{id} [get]
|
||||
// @Router /teams/{id} [get]
|
||||
func (t *Team) ReadOne() (err error) {
|
||||
*t, err = GetTeamByID(t.ID)
|
||||
team, err := GetTeamByID(t.ID)
|
||||
if team != nil {
|
||||
*t = *team
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -160,6 +208,11 @@ func (t *Team) ReadAll(a web.Auth, search string, page int, perPage int) (result
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
err = addMoreInfoToTeams(all)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
numberOfTotalItems, err = x.
|
||||
Table("teams").
|
||||
Join("INNER", "team_members", "team_members.team_id = teams.id").
|
||||
@ -282,7 +335,10 @@ func (t *Team) Update() (err error) {
|
||||
}
|
||||
|
||||
// Get the newly updated team
|
||||
*t, err = GetTeamByID(t.ID)
|
||||
team, err := GetTeamByID(t.ID)
|
||||
if team != nil {
|
||||
*t = *team
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user